1 /* packet-sua.c
2  * Routines for SS7 SCCP-User Adaptation Layer (SUA) dissection
3  * It is hopefully (needs testing) compliant to
4  * https://tools.ietf.org/html/draft-ietf-sigtran-sua-08
5  * https://tools.ietf.org/html/rfc3868
6  *
7  * Copyright 2002, 2003, 2004 Michael Tuexen <tuexen [AT] fh-muenster.de>
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * Copied from README.developer
14  *
15  * SPDX-License-Identifier: GPL-2.0-or-later
16  */
17 
18 #include "config.h"
19 
20 #include <epan/packet.h>
21 #include <epan/address_types.h>
22 #include <epan/prefs.h>
23 #include <epan/sctpppids.h>
24 #include <epan/tap.h>
25 #include <epan/to_str.h>
26 
27 #include <wsutil/str_util.h>
28 
29 #include "packet-mtp3.h"
30 #include "packet-sccp.h"
31 void proto_register_sua(void);
32 void proto_reg_handoff_sua(void);
33 
34 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
35 #define SCTP_PORT_SUA          14001
36 
37 #define RESERVED_1_LENGTH      1
38 #define RESERVED_2_LENGTH      2
39 #define RESERVED_3_LENGTH      3
40 
41 #define VERSION_LENGTH         1
42 #define RESERVED_LENGTH        1
43 #define MESSAGE_CLASS_LENGTH   1
44 #define MESSAGE_TYPE_LENGTH    1
45 #define MESSAGE_LENGTH_LENGTH  4
46 #define COMMON_HEADER_LENGTH   (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
47                                 MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
48 
49 #define COMMON_HEADER_OFFSET   0
50 #define VERSION_OFFSET         COMMON_HEADER_OFFSET
51 #define RESERVED_OFFSET        (VERSION_OFFSET + VERSION_LENGTH)
52 #define MESSAGE_CLASS_OFFSET   (RESERVED_OFFSET + RESERVED_LENGTH)
53 #define MESSAGE_TYPE_OFFSET    (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
54 #define MESSAGE_LENGTH_OFFSET  (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
55 
56 #define PARAMETER_TAG_LENGTH    2
57 #define PARAMETER_LENGTH_LENGTH 2
58 #define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
59 
60 #define PARAMETER_TAG_OFFSET      0
61 #define PARAMETER_LENGTH_OFFSET   (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
62 #define PARAMETER_VALUE_OFFSET    (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
63 #define PARAMETER_HEADER_OFFSET   PARAMETER_TAG_OFFSET
64 
65 #define PROTOCOL_VERSION_RELEASE_1             1
66 
67 static const value_string protocol_version_values[] = {
68   { PROTOCOL_VERSION_RELEASE_1,  "Release 1" },
69   { 0,                           NULL } };
70 
71 #define MESSAGE_CLASS_MGMT_MESSAGE        0
72 #define MESSAGE_CLASS_TFER_MESSAGE        1
73 #define MESSAGE_CLASS_SSNM_MESSAGE        2
74 #define MESSAGE_CLASS_ASPSM_MESSAGE       3
75 #define MESSAGE_CLASS_ASPTM_MESSAGE       4
76 #define MESSAGE_CLASS_CL_MESSAGE          7
77 #define MESSAGE_CLASS_CO_MESSAGE          8
78 #define MESSAGE_CLASS_RKM_MESSAGE         9
79 
80 static const value_string message_class_values[] = {
81   { MESSAGE_CLASS_MGMT_MESSAGE,   "Management messages" },
82   { MESSAGE_CLASS_SSNM_MESSAGE,   "SS7 signalling network management messages" },
83   { MESSAGE_CLASS_ASPSM_MESSAGE,  "ASP state maintenance messages" },
84   { MESSAGE_CLASS_ASPTM_MESSAGE,  "ASP traffic maintenance messages" },
85   { MESSAGE_CLASS_CL_MESSAGE,     "Connectionless messages" },
86   { MESSAGE_CLASS_CO_MESSAGE,     "Connection-Oriented messages" },
87   { MESSAGE_CLASS_RKM_MESSAGE,    "Routing key management Messages" },
88   { 0,                           NULL } };
89 
90 #define MESSAGE_TYPE_ERR                  0
91 #define MESSAGE_TYPE_NTFY                 1
92 
93 #define MESSAGE_TYPE_DUNA                 1
94 #define MESSAGE_TYPE_DAVA                 2
95 #define MESSAGE_TYPE_DAUD                 3
96 #define MESSAGE_TYPE_SCON                 4
97 #define MESSAGE_TYPE_DUPU                 5
98 #define MESSAGE_TYPE_DRST                 6
99 
100 #define MESSAGE_TYPE_UP                   1
101 #define MESSAGE_TYPE_DOWN                 2
102 #define MESSAGE_TYPE_BEAT                 3
103 #define MESSAGE_TYPE_UP_ACK               4
104 #define MESSAGE_TYPE_DOWN_ACK             5
105 #define MESSAGE_TYPE_BEAT_ACK             6
106 
107 #define MESSAGE_TYPE_ACTIVE               1
108 #define MESSAGE_TYPE_INACTIVE             2
109 #define MESSAGE_TYPE_ACTIVE_ACK           3
110 #define MESSAGE_TYPE_INACTIVE_ACK         4
111 
112 #define MESSAGE_TYPE_CLDT                 1
113 #define MESSAGE_TYPE_CLDR                 2
114 
115 #define MESSAGE_TYPE_CORE                 1
116 #define MESSAGE_TYPE_COAK                 2
117 #define MESSAGE_TYPE_COREF                3
118 #define MESSAGE_TYPE_RELRE                4
119 #define MESSAGE_TYPE_RELCO                5
120 #define MESSAGE_TYPE_RESCO                6
121 #define MESSAGE_TYPE_RESRE                7
122 #define MESSAGE_TYPE_CODT                 8
123 #define MESSAGE_TYPE_CODA                 9
124 #define MESSAGE_TYPE_COERR               10
125 #define MESSAGE_TYPE_COIT                11
126 
127 #define MESSAGE_TYPE_REG_REQ              1
128 #define MESSAGE_TYPE_REG_RSP              2
129 #define MESSAGE_TYPE_DEREG_REQ            3
130 #define MESSAGE_TYPE_DEREG_RSP            4
131 
132 
133 static const value_string message_class_type_values[] = {
134   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "Error (ERR)" },
135   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_NTFY,          "Notify (NTFY)" },
136   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUNA,          "Destination unavailable (DUNA)" },
137   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAVA,          "Destination available (DAVA)" },
138   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAUD,          "Destination state audit (DAUD)" },
139   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_SCON,          "SS7 Network congestion state (SCON)" },
140   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUPU,          "Destination userpart unavailable (DUPU)" },
141   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DRST,          "Destination Restricted (DRST)" },
142   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP,            "ASP up (UP)" },
143   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN,          "ASP down (DOWN)" },
144   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT,          "Heartbeat (BEAT)" },
145   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK,        "ASP up ack (UP ACK)" },
146   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP down ack (DOWN ACK)" },
147   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK,      "Heartbeat ack (BEAT ACK)" },
148   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE ,       "ASP active (ACTIVE)" },
149   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE ,     "ASP inactive (INACTIVE)" },
150   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK ,   "ASP active ack (ACTIVE ACK)" },
151   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP inactive ack (INACTIVE ACK)" },
152   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDR ,         "Connectionless Data Response (CLDR)" },
153   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDT ,         "Connectionless Data Transfer (CLDT)" },
154   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CORE ,         "Connection Request (CORE)" },
155   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COAK ,         "Connection Acknowledge (COAK)" },
156   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COREF ,        "Connection Refused (COREF)" },
157   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELRE ,        "Release Request (RELRE)" },
158   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELCO ,        "Release Complete (RELCO)" },
159   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESCO ,        "Reset Confirm (RESCO)" },
160   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESRE ,        "Reset Request (RESRE)" },
161   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODT ,         "Connection Oriented Data Transfer (CODT)" },
162   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODA ,         "Connection Oriented Data Acknowledge (CODA)" },
163   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COERR ,        "Connection Oriented Error (COERR)" },
164   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COIT ,         "Inactivity Test (COIT)" },
165   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_REQ ,      "Registration Request (REG_REQ)" },
166   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_RSP ,      "Registration Response (REG_RSP)" },
167   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_REQ ,    "Deregistration Request (DEREG_REQ)" },
168   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_RSP ,    "Deregistration Response (DEREG_RSP)" },
169   { 0,                           NULL } };
170 
171 static const value_string message_class_type_acro_values[] = {
172   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_ERR,           "ERR" },
173   { MESSAGE_CLASS_MGMT_MESSAGE  * 256 + MESSAGE_TYPE_NTFY,          "NTFY" },
174   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUNA,          "DUNA" },
175   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAVA,          "DAVA" },
176   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DAUD,          "DAUD" },
177   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_SCON,          "SCON" },
178   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DUPU,          "DUPU" },
179   { MESSAGE_CLASS_SSNM_MESSAGE  * 256 + MESSAGE_TYPE_DRST,          "DRST" },
180   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP,            "ASP_UP" },
181   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN,          "ASP_DOWN" },
182   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT,          "BEAT" },
183   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK,        "ASP_UP_ACK" },
184   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK,      "ASP_DOWN_ACK" },
185   { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK,      "BEAT_ACK" },
186   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE ,       "ASP_ACTIVE" },
187   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE ,     "ASP_INACTIVE" },
188   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK ,   "ASP_ACTIVE_ACK" },
189   { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP_INACTIVE_ACK" },
190   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDR ,         "CLDR" },
191   { MESSAGE_CLASS_CL_MESSAGE    * 256 + MESSAGE_TYPE_CLDT ,         "CLDT" },
192   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CORE ,         "CORE" },
193   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COAK ,         "COAK" },
194   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COREF ,        "COREF" },
195   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELRE ,        "RELRE" },
196   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RELCO ,        "RELCO" },
197   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESCO ,        "RESCO" },
198   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_RESRE ,        "RESRE" },
199   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODT ,         "CODT" },
200   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_CODA ,         "CODA" },
201   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COERR ,        "COERR" },
202   { MESSAGE_CLASS_CO_MESSAGE    * 256 + MESSAGE_TYPE_COIT ,         "COIT" },
203   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_REQ ,      "REG_REQ" },
204   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_REG_RSP ,      "REG_RSP" },
205   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_REQ ,    "DEREG_REQ" },
206   { MESSAGE_CLASS_RKM_MESSAGE   * 256 + MESSAGE_TYPE_DEREG_RSP ,    "DEREG_RSP" },
207   { 0,                           NULL } };
208 
209 const value_string sua_co_class_type_acro_values[] = {
210   { MESSAGE_TYPE_CORE ,         "CORE" },
211   { MESSAGE_TYPE_COAK ,         "COAK" },
212   { MESSAGE_TYPE_COREF ,        "COREF" },
213   { MESSAGE_TYPE_RELRE ,        "RELRE" },
214   { MESSAGE_TYPE_RELCO ,        "RELCO" },
215   { MESSAGE_TYPE_RESCO ,        "RESCO" },
216   { MESSAGE_TYPE_RESRE ,        "RESRE" },
217   { MESSAGE_TYPE_CODT ,         "CODT" },
218   { MESSAGE_TYPE_CODA ,         "CODA" },
219   { MESSAGE_TYPE_COERR ,        "COERR" },
220   { MESSAGE_TYPE_COIT ,         "COIT" },
221   { 0, NULL }
222 };
223 
224 /* Initialize the protocol and registered fields */
225 static int proto_sua = -1;
226 static int hf_sua_version = -1;
227 static int hf_sua_reserved = -1;
228 static int hf_sua_message_class = -1;
229 static int hf_sua_message_type = -1;
230 static int hf_sua_message_length = -1;
231 static int hf_sua_parameter_tag = -1;
232 static int hf_sua_v8_parameter_tag = -1;
233 static int hf_sua_parameter_length = -1;
234 static int hf_sua_parameter_value = -1;
235 static int hf_sua_parameter_padding = -1;
236 static int hf_sua_info_string = -1;
237 static int hf_sua_routing_context = -1;
238 static int hf_sua_diagnostic_information_info = -1;
239 static int hf_sua_heartbeat_data = -1;
240 static int hf_sua_traffic_mode_type = -1;
241 static int hf_sua_error_code = -1;
242 static int hf_sua_v8_error_code = -1;
243 static int hf_sua_status_type = -1;
244 static int hf_sua_status_info = -1;
245 static int hf_sua_congestion_level = -1;
246 static int hf_sua_asp_identifier = -1;
247 static int hf_sua_mask = -1;
248 static int hf_sua_dpc = -1;
249 static int hf_sua_registration_status = -1;
250 static int hf_sua_deregistration_status = -1;
251 static int hf_sua_local_routing_key_identifier = -1;
252 
253 static int hf_sua_source_address_routing_indicator = -1;
254 static int hf_sua_source_address_reserved_bits = -1;
255 static int hf_sua_source_address_gt_bit = -1;
256 static int hf_sua_source_address_pc_bit = -1;
257 static int hf_sua_source_address_ssn_bit = -1;
258 static int hf_sua_source_gt_reserved = -1;
259 static int hf_sua_source_gti = -1;
260 static int hf_sua_source_number_of_digits = -1;
261 static int hf_sua_source_translation_type = -1;
262 static int hf_sua_source_numbering_plan = -1;
263 static int hf_sua_source_nature_of_address = -1;
264 static int hf_sua_source_global_title_digits = -1;
265 static int hf_sua_source_point_code = -1;
266 static int hf_sua_source_ssn_reserved = -1;
267 static int hf_sua_source_ssn_number = -1;
268 static int hf_sua_source_ipv4 = -1;
269 static int hf_sua_source_hostname = -1;
270 static int hf_sua_source_ipv6 = -1;
271 
272 static int hf_sua_destination_address_routing_indicator = -1;
273 static int hf_sua_destination_address_reserved_bits = -1;
274 static int hf_sua_destination_address_gt_bit = -1;
275 static int hf_sua_destination_address_pc_bit = -1;
276 static int hf_sua_destination_address_ssn_bit = -1;
277 static int hf_sua_dest_gt_reserved = -1;
278 static int hf_sua_dest_gti = -1;
279 static int hf_sua_dest_number_of_digits = -1;
280 static int hf_sua_dest_translation_type = -1;
281 static int hf_sua_dest_numbering_plan = -1;
282 static int hf_sua_dest_nature_of_address = -1;
283 static int hf_sua_dest_global_title_digits = -1;
284 static int hf_sua_dest_point_code = -1;
285 static int hf_sua_dest_ssn_reserved = -1;
286 static int hf_sua_dest_ssn_number = -1;
287 static int hf_sua_dest_ipv4 = -1;
288 static int hf_sua_dest_hostname = -1;
289 static int hf_sua_dest_ipv6 = -1;
290 
291 static int hf_sua_ss7_hop_counter_counter = -1;
292 static int hf_sua_ss7_hop_counter_reserved = -1;
293 static int hf_sua_destination_reference_number = -1;
294 static int hf_sua_source_reference_number = -1;
295 static int hf_sua_cause_reserved = -1;
296 static int hf_sua_cause_type = -1;
297 static int hf_sua_cause_value = -1;
298 static int hf_sua_sequence_number_reserved = -1;
299 static int hf_sua_sequence_number_rec_number = -1;
300 static int hf_sua_sequence_number_spare_bit = -1;
301 static int hf_sua_sequence_number_sent_number = -1;
302 static int hf_sua_sequence_number_more_data_bit = -1;
303 static int hf_sua_receive_sequence_number_reserved = -1;
304 static int hf_sua_receive_sequence_number_number = -1;
305 static int hf_sua_receive_sequence_number_spare_bit = -1;
306 static int hf_sua_protocol_classes = -1;
307 static int hf_sua_protocol_class_flags = -1;
308 static int hf_sua_asp_capabilities_reserved = -1;
309 static int hf_sua_asp_capabilities_reserved_bits = -1;
310 static int hf_sua_asp_capabilities_a_bit =-1;
311 static int hf_sua_asp_capabilities_b_bit =-1;
312 static int hf_sua_asp_capabilities_c_bit =-1;
313 static int hf_sua_asp_capabilities_d_bit =-1;
314 static int hf_sua_asp_capabilities_interworking = -1;
315 static int hf_sua_credit = -1;
316 static int hf_sua_data = -1;
317 static int hf_sua_cause = -1;
318 static int hf_sua_user = -1;
319 static int hf_sua_network_appearance = -1;
320 static int hf_sua_correlation_id = -1;
321 static int hf_sua_importance_reserved = -1;
322 static int hf_sua_importance = -1;
323 static int hf_sua_message_priority_reserved = -1;
324 static int hf_sua_message_priority = -1;
325 static int hf_sua_protocol_class_reserved = -1;
326 static int hf_sua_return_on_error_bit = -1;
327 static int hf_sua_protocol_class = -1;
328 static int hf_sua_sequence_control = -1;
329 static int hf_sua_first_remaining = -1;
330 static int hf_sua_first_bit = -1;
331 static int hf_sua_number_of_remaining_segments = -1;
332 static int hf_sua_segmentation_reference = -1;
333 static int hf_sua_smi = -1;
334 static int hf_sua_smi_reserved = -1;
335 static int hf_sua_tid_label_start = -1;
336 static int hf_sua_tid_label_end = -1;
337 static int hf_sua_tid_label_value = -1;
338 static int hf_sua_drn_label_start = -1;
339 static int hf_sua_drn_label_end = -1;
340 static int hf_sua_drn_label_value = -1;
341 
342 static int hf_sua_assoc_id = -1;
343 
344 /* Initialize the subtree pointers */
345 static gint ett_sua = -1;
346 static gint ett_sua_parameter = -1;
347 static gint ett_sua_source_address_indicator = -1;
348 static gint ett_sua_destination_address_indicator = -1;
349 static gint ett_sua_affected_destination = -1;
350 static gint ett_sua_first_remaining = -1;
351 static gint ett_sua_sequence_number_rec_number = -1;
352 static gint ett_sua_sequence_number_sent_number = -1;
353 static gint ett_sua_receive_sequence_number_number = -1;
354 static gint ett_sua_return_on_error_bit_and_protocol_class = -1;
355 static gint ett_sua_protocol_classes = -1;
356 static gint ett_sua_assoc = -1;
357 
358 static int sua_tap = -1;
359 
360 static mtp3_addr_pc_t *sua_dpc;
361 static mtp3_addr_pc_t *sua_opc;
362 static guint16 sua_ri;
363 static gchar *sua_source_gt;
364 static gchar *sua_destination_gt;
365 
366 static dissector_handle_t sua_handle;
367 static dissector_handle_t sua_info_str_handle;
368 static dissector_table_t sua_parameter_table;
369 static dissector_table_t sccp_ssn_dissector_table;
370 static heur_dissector_list_t heur_subdissector_list;
371 
372 static guint32  message_class, message_type, drn, srn;
373 
374 static int ss7pc_address_type = -1;
375 
376 #define INVALID_SSN 0xff
377 static guint next_assoc_id = 1;
378 
379 /* Based om  association tracking in the SCCP dissector */
380 typedef struct _sua_assoc_info_t {
381     guint assoc_id;
382     guint32 calling_routing_ind;
383     guint32 called_routing_ind;
384     guint32 calling_dpc;
385     guint32 called_dpc;
386     guint8 calling_ssn;
387     guint8 called_ssn;
388     gboolean has_bw_key;
389     gboolean has_fw_key;
390 } sua_assoc_info_t;
391 
392 static wmem_tree_t* assocs = NULL;
393 static sua_assoc_info_t* assoc;
394 static sua_assoc_info_t no_sua_assoc = {
395     0,      /* assoc_id */
396     0,      /* calling_routing_ind */
397     0,      /* called_routing_ind */
398     0,      /* calling_dpc */
399     0,      /* called_dpc */
400     INVALID_SSN,      /* calling_ssn */
401     INVALID_SSN,      /* called_ssn */
402     FALSE,  /* has_bw_key */
403     FALSE   /* has_fw_key */
404 };
405 
406 static sua_assoc_info_t *
new_assoc(guint32 calling,guint32 called)407 new_assoc(guint32 calling, guint32 called)
408 {
409     sua_assoc_info_t *a = wmem_new0(wmem_file_scope(), sua_assoc_info_t);
410 
411     a->assoc_id               = next_assoc_id++;
412     a->calling_routing_ind    = 0;
413     a->called_routing_ind     = 0;
414     a->calling_dpc            = calling;
415     a->called_dpc             = called;
416     a->calling_ssn            = INVALID_SSN;
417     a->called_ssn             = INVALID_SSN;
418 
419     return a;
420 }
421 
422 static sua_assoc_info_t*
sua_assoc(packet_info * pinfo,address * opc,address * dpc,guint src_rn,guint dst_rn)423 sua_assoc(packet_info* pinfo, address* opc, address* dpc, guint src_rn, guint dst_rn)
424 {
425     guint32 opck, dpck;
426 
427     if (!src_rn && !dst_rn) {
428             return &no_sua_assoc;
429     }
430 
431     opck = opc->type == ss7pc_address_type ? mtp3_pc_hash((const mtp3_addr_pc_t *)opc->data) : g_str_hash(address_to_str(wmem_packet_scope(), opc));
432     dpck = dpc->type == ss7pc_address_type ? mtp3_pc_hash((const mtp3_addr_pc_t *)dpc->data) : g_str_hash(address_to_str(wmem_packet_scope(), dpc));
433 
434     switch (message_type) {
435         case MESSAGE_TYPE_CORE:
436         {
437             /* Calling and called is seen from initiator of CORE */
438             wmem_tree_key_t bw_key[4];
439 
440             bw_key[0].length = 1;
441             bw_key[0].key = &dpck;
442 
443             bw_key[1].length = 1;
444             bw_key[1].key = &opck;
445 
446             bw_key[2].length = 1;
447             bw_key[2].key = &src_rn;
448 
449             bw_key[3].length = 0;
450             bw_key[3].key = NULL;
451 
452 
453             if ( !(assoc = (sua_assoc_info_t *)wmem_tree_lookup32_array(assocs,bw_key)) && ! pinfo->fd->visited) {
454                 assoc = new_assoc(opck, dpck);
455                 wmem_tree_insert32_array(assocs,bw_key,assoc);
456                 assoc->has_bw_key = TRUE;
457                 /*ws_warning("CORE dpck %u,opck %u,src_rn %u",dpck,opck,src_rn);*/
458             }
459             break;
460 
461         }
462 
463         case MESSAGE_TYPE_COAK:
464         {
465             wmem_tree_key_t fw_key[4];
466             wmem_tree_key_t bw_key[4];
467 
468             fw_key[0].length = 1;
469             fw_key[0].key = &dpck;
470 
471             fw_key[1].length = 1;
472             fw_key[1].key = &opck;
473 
474             fw_key[2].length = 1;
475             fw_key[2].key = &src_rn;
476 
477             fw_key[3].length = 0;
478             fw_key[3].key = NULL;
479 
480 
481             bw_key[0].length = 1;
482             bw_key[0].key = &opck;
483 
484             bw_key[1].length = 1;
485             bw_key[1].key = &dpck;
486 
487             bw_key[2].length = 1;
488             bw_key[2].key = &dst_rn;
489 
490             bw_key[3].length = 0;
491             bw_key[3].key = NULL;
492                     /*ws_warning("MESSAGE_TYPE_COAK dst_rn %u,src_rn %u ",dst_rn,src_rn);*/
493                     if ( ( assoc = (sua_assoc_info_t *)wmem_tree_lookup32_array(assocs, bw_key) ) ) {
494                             goto got_assoc;
495                     }
496                     if ( (assoc = (sua_assoc_info_t *)wmem_tree_lookup32_array(assocs, fw_key) ) ) {
497                             goto got_assoc;
498                     }
499 
500             assoc = new_assoc(dpck,opck);
501 
502 got_assoc:
503 
504             pinfo->p2p_dir = P2P_DIR_RECV;
505 
506             if ( ! pinfo->fd->visited && ! assoc->has_bw_key ) {
507                 wmem_tree_insert32_array(assocs, bw_key, assoc);
508                 assoc->has_bw_key = TRUE;
509             }
510 
511             if ( ! pinfo->fd->visited && ! assoc->has_fw_key ) {
512                 wmem_tree_insert32_array(assocs, fw_key, assoc);
513                 assoc->has_fw_key = TRUE;
514             }
515 
516             break;
517         }
518 
519         default:
520         {
521             wmem_tree_key_t key[4];
522 
523             key[0].length = 1;
524             key[0].key = &opck;
525 
526             key[1].length = 1;
527             key[1].key = &dpck;
528 
529             key[2].length = 1;
530             key[2].key = &dst_rn;
531 
532             key[3].length = 0;
533             key[3].key = NULL;
534 
535                     assoc = (sua_assoc_info_t *)wmem_tree_lookup32_array(assocs,key);
536                     /* Should a check be made on pinfo->p2p_dir ??? */
537         break;
538         }
539     }
540 
541     return assoc ? assoc : &no_sua_assoc;
542 }
543 
544 /* stuff for supporting multiple versions */
545 typedef enum {
546   SUA_V08,
547   SUA_RFC
548 } Version_Type;
549 
550 static gint version = SUA_RFC;
551 static gboolean set_addresses = FALSE;
552 
553 static void
554 dissect_parameters(tvbuff_t *tlv_tvb, packet_info *pinfo, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn);
555 
556 static void
dissect_common_header(tvbuff_t * common_header_tvb,packet_info * pinfo,proto_tree * sua_tree)557 dissect_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *sua_tree)
558 {
559 
560   message_class  = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
561   message_type   = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
562 
563   col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(message_class * 256 + message_type, message_class_type_acro_values, "reserved"));
564 
565   if (sua_tree) {
566     /* add the components of the common header to the protocol tree */
567     proto_tree_add_item(sua_tree, hf_sua_version,        common_header_tvb, VERSION_OFFSET,        VERSION_LENGTH,        ENC_BIG_ENDIAN);
568     proto_tree_add_item(sua_tree, hf_sua_reserved,       common_header_tvb, RESERVED_OFFSET,       RESERVED_LENGTH,       ENC_NA);
569     proto_tree_add_item(sua_tree, hf_sua_message_class,  common_header_tvb, MESSAGE_CLASS_OFFSET,  MESSAGE_CLASS_LENGTH,  ENC_BIG_ENDIAN);
570     proto_tree_add_uint_format_value(sua_tree, hf_sua_message_type, common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, message_type, "%s (%u)",
571                                val_to_str_const(message_class * 256 + message_type, message_class_type_values, "reserved"), message_type);
572     proto_tree_add_item(sua_tree, hf_sua_message_length, common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, ENC_BIG_ENDIAN);
573   };
574 }
575 
576 #define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
577 
578 static void
dissect_info_string_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree,proto_item * parameter_item)579 dissect_info_string_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
580 {
581   guint16 info_string_length;
582   tvbuff_t *next_tvb;
583 
584 
585   info_string_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
586   /* If we have a SUA Info String sub dissector call it */
587   if(sua_info_str_handle) {
588     next_tvb = tvb_new_subset_length(parameter_tvb, INFO_STRING_OFFSET, info_string_length);
589     call_dissector(sua_info_str_handle, next_tvb, pinfo, parameter_tree);
590     return;
591   }
592 
593   proto_tree_add_item(parameter_tree, hf_sua_info_string, parameter_tvb, INFO_STRING_OFFSET, info_string_length, ENC_UTF_8|ENC_NA);
594   proto_item_append_text(parameter_item, " (%.*s)", info_string_length,
595                          tvb_format_text(pinfo->pool, parameter_tvb, INFO_STRING_OFFSET, info_string_length));
596 }
597 
598 #define ROUTING_CONTEXT_LENGTH 4
599 
600 static void
dissect_routing_context_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)601 dissect_routing_context_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
602 {
603   guint16 number_of_contexts, context_number;
604   gint context_offset;
605 
606   number_of_contexts = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / 4;
607   context_offset = PARAMETER_VALUE_OFFSET;
608   for(context_number=0; context_number < number_of_contexts; context_number++) {
609     proto_tree_add_item(parameter_tree, hf_sua_routing_context, parameter_tvb, context_offset, ROUTING_CONTEXT_LENGTH, ENC_BIG_ENDIAN);
610     context_offset += ROUTING_CONTEXT_LENGTH;
611   };
612   proto_item_append_text(parameter_item, " (%u context%s)", number_of_contexts, plurality(number_of_contexts, "", "s"));
613 }
614 
615 #define DIAGNOSTIC_INFO_OFFSET PARAMETER_VALUE_OFFSET
616 
617 static void
dissect_diagnostic_information_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)618 dissect_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
619 {
620   guint16 diag_info_length;
621 
622   diag_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
623   proto_tree_add_item(parameter_tree, hf_sua_diagnostic_information_info, parameter_tvb, DIAGNOSTIC_INFO_OFFSET, diag_info_length, ENC_NA);
624   proto_item_append_text(parameter_item, " (%u byte%s)", diag_info_length, plurality(diag_info_length, "", "s"));
625 }
626 
627 #define HEARTBEAT_DATA_OFFSET PARAMETER_VALUE_OFFSET
628 
629 static void
dissect_heartbeat_data_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)630 dissect_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
631 {
632   guint16 heartbeat_data_length;
633 
634   heartbeat_data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
635   proto_tree_add_item(parameter_tree, hf_sua_heartbeat_data, parameter_tvb, HEARTBEAT_DATA_OFFSET, heartbeat_data_length, ENC_NA);
636   proto_item_append_text(parameter_item, " (%u byte%s)", heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
637 }
638 
639 #define TRAFFIC_MODE_TYPE_OFFSET PARAMETER_VALUE_OFFSET
640 #define TRAFFIC_MODE_TYPE_LENGTH 4
641 
642 static const value_string traffic_mode_type_values[] = {
643   { 1, "Over-ride" },
644   { 2, "Load-share" },
645   { 3, "Broadcast" },
646   { 0, NULL } };
647 
648 static void
dissect_traffic_mode_type_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)649 dissect_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
650 {
651   proto_tree_add_item(parameter_tree, hf_sua_traffic_mode_type, parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH, ENC_BIG_ENDIAN);
652   proto_item_append_text(parameter_item, " (%s)", val_to_str_const(tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET), traffic_mode_type_values, "unknown"));
653 }
654 
655 #define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
656 #define ERROR_CODE_LENGTH 4
657 
658 static const value_string v8_error_code_values[] = {
659   { 0x01, "Invalid version" },
660   { 0x02, "Invalid interface identifier" },
661   { 0x03, "Unsupported message class" },
662   { 0x04, "Unsupported message type" },
663   { 0x05, "Unsupported traffic handling mode" },
664   { 0x06, "Unexpected message" },
665   { 0x07, "Protocol error" },
666   { 0x09, "Invalid stream identifier" },
667   { 0x0d, "Refused - management blocking" },
668   { 0x0e, "ASP identifier required" },
669   { 0x0f, "Invalid ASP identifier" },
670   { 0x11, "Invalid parameter value" },
671   { 0x12, "Parameter field error" },
672   { 0x13, "Unexpected parameter" },
673   { 0x14, "Destination status unknown" },
674   { 0x15, "Invalid network appearance" },
675   { 0x16, "Missing parameter" },
676   { 0x17, "Routing key change refused" },
677   { 0x18, "Invalid loadsharing label" },
678   { 0,    NULL } };
679 
680 static void
dissect_v8_error_code_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)681 dissect_v8_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
682 {
683   proto_tree_add_item(parameter_tree, hf_sua_v8_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, ENC_BIG_ENDIAN);
684   proto_item_append_text(parameter_item, " (%s)", val_to_str_const(tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET), v8_error_code_values, "unknown"));
685 }
686 
687 static const value_string error_code_values[] = {
688   { 0x01, "Invalid version" },
689   { 0x03, "Unsupported message class" },
690   { 0x04, "Unsupported message type" },
691   { 0x05, "Unsupported traffic handling mode" },
692   { 0x06, "Unexpected message" },
693   { 0x07, "Protocol error" },
694   { 0x09, "Invalid stream identifier" },
695   { 0x0d, "Refused - management blocking" },
696   { 0x0e, "ASP identifier required" },
697   { 0x0f, "Invalid ASP identifier" },
698   { 0x11, "Invalid parameter value" },
699   { 0x12, "Parameter field error" },
700   { 0x13, "Unexpected parameter" },
701   { 0x14, "Destination status unknown" },
702   { 0x15, "Invalid network appearance" },
703   { 0x16, "Missing parameter" },
704   { 0x19, "Invalid routing context" },
705   { 0x1a, "No configured AS for ASP" },
706   { 0x1b, "Subsystem status unknown" },
707   { 0x1c, "Invalid loadsharing label" },
708   { 0,    NULL } };
709 
710 static void
dissect_error_code_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)711 dissect_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
712 {
713   proto_tree_add_item(parameter_tree, hf_sua_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, ENC_BIG_ENDIAN);
714   proto_item_append_text(parameter_item, " (%s)", val_to_str_const(tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET), error_code_values, "unknown"));
715 }
716 
717 #define STATUS_TYPE_LENGTH 2
718 #define STATUS_INFO_LENGTH 2
719 #define STATUS_TYPE_OFFSET PARAMETER_VALUE_OFFSET
720 #define STATUS_INFO_OFFSET (STATUS_TYPE_OFFSET + STATUS_TYPE_LENGTH)
721 
722 #define AS_STATE_CHANGE_TYPE       1
723 #define OTHER_TYPE                 2
724 
725 static const value_string status_type_values[] = {
726   { AS_STATE_CHANGE_TYPE,            "Application server state change" },
727   { OTHER_TYPE,                      "Other" },
728   { 0,                               NULL } };
729 
730 #define RESERVED_INFO              1
731 #define AS_INACTIVE_INFO           2
732 #define AS_ACTIVE_INFO             3
733 #define AS_PENDING_INFO            4
734 
735 #define INSUFFICIENT_ASP_RES_INFO  1
736 #define ALTERNATE_ASP_ACTIVE_INFO  2
737 #define ASP_FAILURE                3
738 
739 static const value_string status_type_info_values[] = {
740   { AS_STATE_CHANGE_TYPE * 256 * 256 + RESERVED_INFO,             "Reserved" },
741   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_INACTIVE_INFO,          "Application server inactive" },
742   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_ACTIVE_INFO,            "Application server active" },
743   { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_PENDING_INFO,           "Application server pending" },
744   { OTHER_TYPE           * 256 * 256 + INSUFFICIENT_ASP_RES_INFO, "Insufficient ASP resources active in AS" },
745   { OTHER_TYPE           * 256 * 256 + ALTERNATE_ASP_ACTIVE_INFO, "Alternate ASP active" },
746   { OTHER_TYPE           * 256 * 256 + ASP_FAILURE,               "ASP Failure" },
747   {0,                           NULL } };
748 
749 static void
dissect_status_type_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)750 dissect_status_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
751 {
752   guint16 status_type, status_info;
753 
754   status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET);
755   status_info = tvb_get_ntohs(parameter_tvb, STATUS_INFO_OFFSET);
756 
757   proto_tree_add_item(parameter_tree, hf_sua_status_type, parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH, ENC_BIG_ENDIAN);
758   proto_tree_add_uint_format_value(parameter_tree, hf_sua_status_info, parameter_tvb, STATUS_INFO_OFFSET, STATUS_INFO_LENGTH,
759                              status_info, "%s (%u)", val_to_str_const(status_type * 256 * 256 + status_info, status_type_info_values, "unknown"), status_info);
760 
761   proto_item_append_text(parameter_item, " (%s)", val_to_str_const(status_type * 256 * 256 + status_info, status_type_info_values, "unknown"));
762 }
763 
764 #define ASP_IDENTIFIER_LENGTH 4
765 #define ASP_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
766 
767 static void
dissect_asp_identifier_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)768 dissect_asp_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
769 {
770   proto_tree_add_item(parameter_tree, hf_sua_asp_identifier, parameter_tvb, ASP_IDENTIFIER_OFFSET, ASP_IDENTIFIER_LENGTH, ENC_BIG_ENDIAN);
771   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, ASP_IDENTIFIER_OFFSET));
772 }
773 
774 #define AFFECTED_MASK_LENGTH 1
775 #define AFFECTED_DPC_LENGTH  3
776 #define AFFECTED_DESTINATION_LENGTH (AFFECTED_MASK_LENGTH + AFFECTED_DPC_LENGTH)
777 
778 #define AFFECTED_MASK_OFFSET 0
779 #define AFFECTED_DPC_OFFSET  1
780 
781 static void
dissect_affected_destinations_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)782 dissect_affected_destinations_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
783 {
784   guint16 number_of_destinations, destination_number;
785   gint destination_offset;
786   proto_item *dpc_item;
787 
788   number_of_destinations= (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / 4;
789   destination_offset = PARAMETER_VALUE_OFFSET;
790   for(destination_number=0; destination_number < number_of_destinations; destination_number++) {
791     proto_tree_add_item(parameter_tree, hf_sua_mask, parameter_tvb, destination_offset + AFFECTED_MASK_OFFSET, AFFECTED_MASK_LENGTH, ENC_BIG_ENDIAN);
792     dpc_item = proto_tree_add_item(parameter_tree, hf_sua_dpc,  parameter_tvb, destination_offset + AFFECTED_DPC_OFFSET,  AFFECTED_DPC_LENGTH,  ENC_BIG_ENDIAN);
793     if (mtp3_pc_structured())
794       proto_item_append_text(dpc_item, " (%s)", mtp3_pc_to_str(tvb_get_ntoh24(parameter_tvb, destination_offset + AFFECTED_DPC_OFFSET)));
795     destination_offset += AFFECTED_DESTINATION_LENGTH;
796   }
797   proto_item_append_text(parameter_item, " (%u destination%s)", number_of_destinations, plurality(number_of_destinations, "", "s"));
798 }
799 
800 #define CORRELATION_ID_LENGTH 4
801 #define CORRELATION_ID_OFFSET PARAMETER_VALUE_OFFSET
802 
803 static void
dissect_correlation_id_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)804 dissect_correlation_id_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
805 {
806   proto_tree_add_item(parameter_tree, hf_sua_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
807   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
808 }
809 
810 static void
dissect_registration_result_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree)811 dissect_registration_result_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
812 {
813   tvbuff_t *parameters_tvb;
814 
815   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, PARAMETER_VALUE_OFFSET);
816   dissect_parameters(parameters_tvb, pinfo, parameter_tree, NULL, NULL, NULL);
817 }
818 
819 static void
dissect_deregistration_result_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree)820 dissect_deregistration_result_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
821 {
822   tvbuff_t *parameters_tvb;
823 
824   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, PARAMETER_VALUE_OFFSET);
825   dissect_parameters(parameters_tvb, pinfo, parameter_tree, NULL, NULL, NULL);
826 }
827 
828 #define REGISTRATION_STATUS_LENGTH 4
829 #define REGISTRATION_STATUS_OFFSET PARAMETER_VALUE_OFFSET
830 
831 static const value_string registration_status_values[] = {
832   {  0,            "Successfully registered" },
833   {  1,            "Error - unknown" },
834   {  2,            "Error - invalid destination address" },
835   {  3,            "Error - invalid network appearance" },
836   {  4,            "Error - invalid routing key" },
837   {  5,            "Error - permission denied" },
838   {  6,            "Error - cannot support unique routing" },
839   {  7,            "Error - routing key not currently provisioned" },
840   {  8,            "Error - insufficient resources" },
841   {  9,            "Error - unsupported RK parameter field" },
842   { 10,            "Error - unsupported/invalid traffic mode type" },
843   { 11,            "Error - routing key change refused" },
844   {  0,            NULL } };
845 
846 static void
dissect_registration_status_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)847 dissect_registration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
848 {
849   proto_tree_add_item(parameter_tree, hf_sua_registration_status, parameter_tvb, REGISTRATION_STATUS_OFFSET, REGISTRATION_STATUS_LENGTH, ENC_BIG_ENDIAN);
850   proto_item_append_text(parameter_item, " (%s)", val_to_str_const(tvb_get_ntohl(parameter_tvb, REGISTRATION_STATUS_OFFSET), registration_status_values, "unknown"));
851 }
852 
853 #define DEREGISTRATION_STATUS_LENGTH 4
854 #define DEREGISTRATION_STATUS_OFFSET PARAMETER_VALUE_OFFSET
855 
856 static const value_string deregistration_status_values[] = {
857   {  0,            "Successfully deregistered" },
858   {  1,            "Error - unknown" },
859   {  2,            "Error - invalid routing context" },
860   {  3,            "Error - permission denied" },
861   {  4,            "Error - not registered" },
862   {  5,            "Error - ASP currently active for routing context" },
863   {  0,            NULL } };
864 
865 static void
dissect_deregistration_status_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)866 dissect_deregistration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
867 {
868   proto_tree_add_item(parameter_tree, hf_sua_deregistration_status, parameter_tvb, DEREGISTRATION_STATUS_OFFSET, DEREGISTRATION_STATUS_LENGTH, ENC_BIG_ENDIAN);
869   proto_item_append_text(parameter_item, " (%s)", val_to_str_const(tvb_get_ntohl(parameter_tvb, DEREGISTRATION_STATUS_OFFSET), deregistration_status_values, "unknown"));
870 }
871 
872 #define LOCAL_ROUTING_KEY_IDENTIFIER_LENGTH 4
873 #define LOCAL_ROUTING_KEY_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
874 
875 static void
dissect_local_routing_key_identifier_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)876 dissect_local_routing_key_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
877 {
878   proto_tree_add_item(parameter_tree, hf_sua_local_routing_key_identifier, parameter_tvb, LOCAL_ROUTING_KEY_IDENTIFIER_OFFSET, LOCAL_ROUTING_KEY_IDENTIFIER_LENGTH, ENC_BIG_ENDIAN);
879   proto_item_append_text(parameter_item, " (%d)", tvb_get_ntohl(parameter_tvb, LOCAL_ROUTING_KEY_IDENTIFIER_OFFSET));
880 }
881 
882 #define SS7_HOP_COUNTER_LENGTH 1
883 #define SS7_HOP_COUNTER_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
884 
885 static void
dissect_ss7_hop_counter_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)886 dissect_ss7_hop_counter_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
887 {
888   proto_tree_add_item(parameter_tree, hf_sua_ss7_hop_counter_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH,      ENC_NA);
889   proto_tree_add_item(parameter_tree, hf_sua_ss7_hop_counter_counter,  parameter_tvb, SS7_HOP_COUNTER_OFFSET, SS7_HOP_COUNTER_LENGTH, ENC_BIG_ENDIAN);
890   proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb,  SS7_HOP_COUNTER_OFFSET));
891 }
892 
893 #define ROUTING_INDICATOR_LENGTH  2
894 #define ADDRESS_INDICATOR_LENGTH  2
895 
896 #define ROUTING_INDICATOR_OFFSET  PARAMETER_VALUE_OFFSET
897 #define ADDRESS_INDICATOR_OFFSET  (ROUTING_INDICATOR_OFFSET + ROUTING_INDICATOR_LENGTH)
898 #define ADDRESS_PARAMETERS_OFFSET (ADDRESS_INDICATOR_OFFSET + ADDRESS_INDICATOR_LENGTH)
899 
900 #define RESERVED_ROUTING_INDICATOR              0
901 #define ROUTE_ON_GT_ROUTING_INDICATOR           1
902 #define ROUTE_ON_SSN_PC_ROUTING_INDICATOR       2
903 #define ROUTE_ON_HOSTNAMEROUTING_INDICATOR      3
904 #define ROUTE_ON_SSN_IP_ROUTING_INDICATOR       4
905 
906 static const value_string routing_indicator_values[] = {
907   { RESERVED_ROUTING_INDICATOR,            "Reserved" },
908   { ROUTE_ON_GT_ROUTING_INDICATOR,         "Route on Global Title" },
909   { ROUTE_ON_SSN_PC_ROUTING_INDICATOR,     "Route on SSN + PC" },
910   { ROUTE_ON_HOSTNAMEROUTING_INDICATOR,    "Route on Hostname" },
911   { ROUTE_ON_SSN_IP_ROUTING_INDICATOR,     "Route on SSN + IP Address" },
912   { 0,                                     NULL } };
913 
914 #define ADDRESS_RESERVED_BITMASK 0xfff8
915 #define ADDRESS_GT_BITMASK       0x0004
916 #define ADDRESS_PC_BITMASK       0x0002
917 #define ADDRESS_SSN_BITMASK      0x0001
918 
919 static void
dissect_source_address_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree,guint8 * ssn)920 dissect_source_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, guint8 *ssn)
921 {
922   proto_tree *address_indicator_tree;
923   tvbuff_t *parameters_tvb;
924 
925   sua_ri = tvb_get_ntohs(parameter_tvb, ROUTING_INDICATOR_OFFSET);
926 
927   if(parameter_tree) {
928     proto_tree_add_item(parameter_tree, hf_sua_source_address_routing_indicator, parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
929     address_indicator_tree = proto_tree_add_subtree(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ett_sua_source_address_indicator, NULL, "Address Indicator");
930     proto_tree_add_item(address_indicator_tree, hf_sua_source_address_reserved_bits, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
931     proto_tree_add_item(address_indicator_tree, hf_sua_source_address_gt_bit,        parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
932     proto_tree_add_item(address_indicator_tree, hf_sua_source_address_pc_bit,        parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
933     proto_tree_add_item(address_indicator_tree, hf_sua_source_address_ssn_bit,       parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
934   }
935 
936   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, ADDRESS_PARAMETERS_OFFSET);
937   dissect_parameters(parameters_tvb, pinfo, parameter_tree, NULL, ssn, NULL);
938 }
939 
940 static void
dissect_destination_address_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree,guint8 * ssn)941 dissect_destination_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, guint8 *ssn)
942 {
943   proto_tree *address_indicator_tree;
944   tvbuff_t *parameters_tvb;
945 
946   sua_ri = tvb_get_ntohs(parameter_tvb, ROUTING_INDICATOR_OFFSET);
947 
948   if(parameter_tree) {
949     proto_tree_add_item(parameter_tree, hf_sua_destination_address_routing_indicator, parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
950     address_indicator_tree = proto_tree_add_subtree(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ett_sua_destination_address_indicator, NULL, "Address Indicator");
951     proto_tree_add_item(address_indicator_tree, hf_sua_destination_address_reserved_bits, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
952     proto_tree_add_item(address_indicator_tree, hf_sua_destination_address_gt_bit,        parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
953     proto_tree_add_item(address_indicator_tree, hf_sua_destination_address_pc_bit,        parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
954     proto_tree_add_item(address_indicator_tree, hf_sua_destination_address_ssn_bit,       parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, ENC_BIG_ENDIAN);
955   }
956 
957   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, ADDRESS_PARAMETERS_OFFSET);
958   dissect_parameters(parameters_tvb, pinfo, parameter_tree, NULL, NULL, ssn);
959 }
960 
961 #define SOURCE_REFERENCE_NUMBER_LENGTH 4
962 #define SOURCE_REFERENCE_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
963 
964 static void
dissect_source_reference_number_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)965 dissect_source_reference_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
966 {
967   srn = tvb_get_ntohl(parameter_tvb, SOURCE_REFERENCE_NUMBER_OFFSET);
968   proto_tree_add_item(parameter_tree, hf_sua_source_reference_number, parameter_tvb, SOURCE_REFERENCE_NUMBER_OFFSET, SOURCE_REFERENCE_NUMBER_LENGTH, ENC_BIG_ENDIAN);
969   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, SOURCE_REFERENCE_NUMBER_OFFSET));
970 }
971 
972 #define DESTINATION_REFERENCE_NUMBER_LENGTH 4
973 #define DESTINATION_REFERENCE_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
974 
975 static void
dissect_destination_reference_number_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)976 dissect_destination_reference_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
977 {
978   drn = tvb_get_ntohl(parameter_tvb, DESTINATION_REFERENCE_NUMBER_OFFSET);
979   proto_tree_add_item(parameter_tree, hf_sua_destination_reference_number, parameter_tvb, DESTINATION_REFERENCE_NUMBER_OFFSET, DESTINATION_REFERENCE_NUMBER_LENGTH, ENC_BIG_ENDIAN);
980   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, DESTINATION_REFERENCE_NUMBER_OFFSET));
981 }
982 
983 #define CAUSE_TYPE_LENGTH 1
984 #define CAUSE_VALUE_LENGTH 1
985 
986 #define CAUSE_TYPE_OFFSET  (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
987 #define CAUSE_VALUE_OFFSET (CAUSE_TYPE_OFFSET + CAUSE_TYPE_LENGTH)
988 
989 #define CAUSE_TYPE_RETURN  0x1
990 #define CAUSE_TYPE_REFUSAL 0x2
991 #define CAUSE_TYPE_RELEASE 0x3
992 #define CAUSE_TYPE_RESET   0x4
993 #define CAUSE_TYPE_ERROR   0x5
994 static const value_string cause_type_values[] = {
995   { CAUSE_TYPE_RETURN,  "Return Cause" },
996   { CAUSE_TYPE_REFUSAL, "Refusal Cause" },
997   { CAUSE_TYPE_RELEASE, "Release Cause" },
998   { CAUSE_TYPE_RESET,   "Reset Cause" },
999   { CAUSE_TYPE_ERROR,   "Error cause" },
1000   { 0,                  NULL } };
1001 
1002 static void
dissect_sccp_cause_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1003 dissect_sccp_cause_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1004 {
1005   guint8 cause_type, cause;
1006   proto_item *pi;
1007   const gchar *cause_string;
1008 
1009   proto_tree_add_item(parameter_tree, hf_sua_cause_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH,  ENC_NA);
1010   proto_tree_add_item(parameter_tree, hf_sua_cause_type,     parameter_tvb, CAUSE_TYPE_OFFSET,      CAUSE_TYPE_LENGTH,  ENC_BIG_ENDIAN);
1011   cause_type = tvb_get_guint8(parameter_tvb, CAUSE_TYPE_OFFSET);
1012   pi = proto_tree_add_item(parameter_tree, hf_sua_cause_value, parameter_tvb, CAUSE_VALUE_OFFSET,   CAUSE_VALUE_LENGTH, ENC_BIG_ENDIAN);
1013   cause = tvb_get_guint8(parameter_tvb, CAUSE_VALUE_OFFSET);
1014 
1015   switch (cause_type) {
1016   case CAUSE_TYPE_RETURN:
1017     cause_string = val_to_str_const(cause, sccp_return_cause_values, "unknown");
1018     break;
1019   case CAUSE_TYPE_REFUSAL:
1020     cause_string = val_to_str_const(cause, sccp_refusal_cause_values, "unknown");
1021     break;
1022   case CAUSE_TYPE_RELEASE:
1023     cause_string = val_to_str_const(cause, sccp_release_cause_values, "unknown");
1024     break;
1025   case CAUSE_TYPE_RESET:
1026     cause_string = val_to_str_const(cause, sccp_reset_cause_values, "unknown");
1027     break;
1028   case CAUSE_TYPE_ERROR:
1029     cause_string = val_to_str_const(cause, sccp_error_cause_values, "unknown");
1030     break;
1031   default:
1032     cause_string = "unknown";
1033   }
1034 
1035   proto_item_append_text(pi, " (%s)", cause_string);
1036   proto_item_append_text(parameter_item, " (%s: %s)", val_to_str_const(cause_type, cause_type_values, "unknown"), cause_string);
1037 }
1038 
1039 #define SEQUENCE_NUMBER_REC_SEQ_LENGTH  1
1040 #define SEQUENCE_NUMBER_SENT_SEQ_LENGTH 1
1041 #define SEQUENCE_NUMBER_REC_SEQ_OFFSET  (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
1042 #define SEQUENCE_NUMBER_SENT_SEQ_OFFSET (SEQUENCE_NUMBER_REC_SEQ_OFFSET + SEQUENCE_NUMBER_REC_SEQ_LENGTH)
1043 
1044 #define SEQ_NUM_MASK       0xFE
1045 #define SPARE_BIT_MASK     0x01
1046 #define MORE_DATA_BIT_MASK 0x01
1047 
1048 static const true_false_string more_data_bit_value = {
1049   "More Data",
1050   "Not More Data"
1051 };
1052 
1053 static void
dissect_sequence_number_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree)1054 dissect_sequence_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1055 {
1056   proto_tree *sent_sequence_number_tree;
1057   proto_tree *receive_sequence_number_tree;
1058 
1059   proto_tree_add_item(parameter_tree, hf_sua_sequence_number_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH, ENC_NA);
1060 
1061   receive_sequence_number_tree = proto_tree_add_subtree(parameter_tree, parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET, SEQUENCE_NUMBER_REC_SEQ_LENGTH,
1062                                             ett_sua_sequence_number_rec_number, NULL, "Receive Sequence Number");
1063   proto_tree_add_item(receive_sequence_number_tree, hf_sua_sequence_number_rec_number,    parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET, SEQUENCE_NUMBER_REC_SEQ_LENGTH, ENC_BIG_ENDIAN);
1064   proto_tree_add_item(receive_sequence_number_tree, hf_sua_sequence_number_more_data_bit, parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET, SEQUENCE_NUMBER_REC_SEQ_LENGTH, ENC_BIG_ENDIAN);
1065 
1066   sent_sequence_number_tree = proto_tree_add_subtree(parameter_tree, parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET, SEQUENCE_NUMBER_SENT_SEQ_LENGTH,
1067                                             ett_sua_sequence_number_sent_number, NULL, "Sent Sequence Number");
1068   proto_tree_add_item(sent_sequence_number_tree, hf_sua_sequence_number_sent_number, parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET, SEQUENCE_NUMBER_SENT_SEQ_LENGTH, ENC_BIG_ENDIAN);
1069   proto_tree_add_item(sent_sequence_number_tree, hf_sua_sequence_number_spare_bit,   parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET, SEQUENCE_NUMBER_SENT_SEQ_LENGTH, ENC_BIG_ENDIAN);
1070 }
1071 
1072 #define RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH 1
1073 #define RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1074 
1075 static void
dissect_receive_sequence_number_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree)1076 dissect_receive_sequence_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1077 {
1078   proto_tree *receive_sequence_number_tree;
1079 
1080   proto_tree_add_item(parameter_tree, hf_sua_receive_sequence_number_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, ENC_NA);
1081   receive_sequence_number_tree = proto_tree_add_subtree(parameter_tree, parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH,
1082                             ett_sua_receive_sequence_number_number, NULL, "Receive Sequence Number");
1083   proto_tree_add_item(receive_sequence_number_tree, hf_sua_receive_sequence_number_number,    parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH, ENC_BIG_ENDIAN);
1084   proto_tree_add_item(receive_sequence_number_tree, hf_sua_receive_sequence_number_spare_bit, parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH, ENC_BIG_ENDIAN);
1085 }
1086 
1087 #define PROTOCOL_CLASSES_LENGTH        1
1088 #define INTERWORKING_LENGTH            1
1089 #define PROTOCOL_CLASSES_OFFSET        (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
1090 #define INTERWORKING_OFFSET            (PROTOCOL_CLASSES_OFFSET + PROTOCOL_CLASSES_LENGTH)
1091 
1092 #define A_BIT_MASK 0x08
1093 #define B_BIT_MASK 0x04
1094 #define C_BIT_MASK 0x02
1095 #define D_BIT_MASK 0x01
1096 #define RESERVED_BITS_MASK 0xF0
1097 
1098 static const value_string interworking_values[] = {
1099   { 0x0,   "No Interworking with SS7 Networks" },
1100   { 0x1,   "IP-Signalling Endpoint interworking with with SS7 networks" },
1101   { 0x2,   "Signalling Gateway" },
1102   { 0x3,   "Relay Node Support" },
1103   { 0,     NULL } };
1104 
1105 static void
dissect_asp_capabilities_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree)1106 dissect_asp_capabilities_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1107 {
1108   static int * const capabilities[] = {
1109     &hf_sua_asp_capabilities_reserved_bits,
1110     &hf_sua_asp_capabilities_a_bit,
1111     &hf_sua_asp_capabilities_b_bit,
1112     &hf_sua_asp_capabilities_c_bit,
1113     &hf_sua_asp_capabilities_d_bit,
1114     NULL
1115    };
1116 
1117   proto_tree_add_item(parameter_tree, hf_sua_asp_capabilities_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH, ENC_NA);
1118   proto_tree_add_bitmask(parameter_tree, parameter_tvb, PROTOCOL_CLASSES_OFFSET, hf_sua_protocol_classes, ett_sua_protocol_classes, capabilities, ENC_BIG_ENDIAN);
1119   proto_tree_add_item(parameter_tree, hf_sua_asp_capabilities_interworking, parameter_tvb, INTERWORKING_OFFSET, INTERWORKING_LENGTH, ENC_BIG_ENDIAN);
1120 }
1121 
1122 #define CREDIT_LENGTH 4
1123 #define CREDIT_OFFSET PARAMETER_VALUE_OFFSET
1124 
1125 static void
dissect_credit_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1126 dissect_credit_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1127 {
1128   proto_tree_add_item(parameter_tree, hf_sua_credit, parameter_tvb, CREDIT_OFFSET, CREDIT_LENGTH, ENC_BIG_ENDIAN);
1129   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CREDIT_OFFSET));
1130 }
1131 
1132 #define DATA_PARAMETER_DATA_OFFSET PARAMETER_VALUE_OFFSET
1133 
1134 static void
dissect_data_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item,tvbuff_t ** data_tvb)1135 dissect_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, tvbuff_t **data_tvb)
1136 {
1137   guint16 data_length;
1138 
1139   data_length    = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1140 
1141   if(parameter_tree) {
1142     proto_tree_add_item(parameter_tree, hf_sua_data, parameter_tvb, DATA_PARAMETER_DATA_OFFSET, data_length, ENC_NA);
1143     proto_item_append_text(parameter_item, " (SS7 message of %u byte%s)", data_length, plurality(data_length, "", "s"));
1144   }
1145 
1146   if(data_tvb)
1147   {
1148     *data_tvb = tvb_new_subset_length(parameter_tvb, PARAMETER_VALUE_OFFSET, data_length);
1149   }
1150 }
1151 
1152 
1153 #define CAUSE_LENGTH 2
1154 #define USER_LENGTH  2
1155 #define CAUSE_OFFSET PARAMETER_VALUE_OFFSET
1156 #define USER_OFFSET (CAUSE_OFFSET + CAUSE_LENGTH)
1157 
1158 static const value_string cause_values[] = {
1159   { 0x0,  "Remote SCCP unavailable, Reason unknown" },
1160   { 0x2,  "Remote SCCP unequipped" },
1161   { 0x3,  "Remote SCCP inaccessible" },
1162   { 0,    NULL } };
1163 
1164 static void
dissect_user_cause_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree)1165 dissect_user_cause_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1166 {
1167   proto_tree_add_item(parameter_tree, hf_sua_cause, parameter_tvb, CAUSE_OFFSET, CAUSE_LENGTH, ENC_BIG_ENDIAN);
1168   proto_tree_add_item(parameter_tree, hf_sua_user,  parameter_tvb, USER_OFFSET,  USER_LENGTH,  ENC_BIG_ENDIAN);
1169 }
1170 
1171 #define NETWORK_APPEARANCE_LENGTH 4
1172 #define NETWORK_APPEARANCE_OFFSET PARAMETER_VALUE_OFFSET
1173 
1174 static void
dissect_network_appearance_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1175 dissect_network_appearance_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1176 {
1177   proto_tree_add_item(parameter_tree, hf_sua_network_appearance, parameter_tvb, NETWORK_APPEARANCE_OFFSET, NETWORK_APPEARANCE_LENGTH, ENC_BIG_ENDIAN);
1178   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, NETWORK_APPEARANCE_OFFSET));
1179 }
1180 
1181 static void
dissect_routing_key_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree)1182 dissect_routing_key_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
1183 {
1184   tvbuff_t *parameters_tvb;
1185 
1186   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, PARAMETER_VALUE_OFFSET);
1187   dissect_parameters(parameters_tvb, pinfo, parameter_tree, NULL, NULL, NULL);
1188 }
1189 #define DRN_START_LENGTH 1
1190 #define DRN_END_LENGTH 1
1191 #define DRN_VALUE_LENGTH 2
1192 
1193 #define DRN_START_OFFSET PARAMETER_VALUE_OFFSET
1194 #define DRN_END_OFFSET   (DRN_START_OFFSET + DRN_START_LENGTH)
1195 #define DRN_VALUE_OFFSET (DRN_END_OFFSET + DRN_END_LENGTH)
1196 
1197 static void
dissect_drn_label_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree)1198 dissect_drn_label_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1199 {
1200   proto_tree_add_item(parameter_tree, hf_sua_drn_label_start, parameter_tvb, DRN_START_OFFSET, DRN_START_LENGTH, ENC_BIG_ENDIAN);
1201   proto_tree_add_item(parameter_tree, hf_sua_drn_label_end,   parameter_tvb, DRN_END_OFFSET,   DRN_END_LENGTH,   ENC_BIG_ENDIAN);
1202   proto_tree_add_item(parameter_tree, hf_sua_drn_label_value, parameter_tvb, DRN_VALUE_OFFSET, DRN_VALUE_LENGTH, ENC_BIG_ENDIAN);
1203 }
1204 
1205 #define TID_START_LENGTH 1
1206 #define TID_END_LENGTH 1
1207 #define TID_VALUE_LENGTH 2
1208 
1209 #define TID_START_OFFSET PARAMETER_VALUE_OFFSET
1210 #define TID_END_OFFSET   (TID_START_OFFSET + TID_START_LENGTH)
1211 #define TID_VALUE_OFFSET (TID_END_OFFSET + TID_END_LENGTH)
1212 
1213 static void
dissect_tid_label_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree)1214 dissect_tid_label_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1215 {
1216   proto_tree_add_item(parameter_tree, hf_sua_tid_label_start, parameter_tvb, TID_START_OFFSET, TID_START_LENGTH, ENC_BIG_ENDIAN);
1217   proto_tree_add_item(parameter_tree, hf_sua_tid_label_end,   parameter_tvb, TID_END_OFFSET,   TID_END_LENGTH,   ENC_BIG_ENDIAN);
1218   proto_tree_add_item(parameter_tree, hf_sua_tid_label_value, parameter_tvb, TID_VALUE_OFFSET, TID_VALUE_LENGTH, ENC_BIG_ENDIAN);
1219 }
1220 
1221 #define ADDRESS_RANGE_ADDRESS_PARAMETERS_OFFSET  PARAMETER_VALUE_OFFSET
1222 
1223 static void
dissect_address_range_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree)1224 dissect_address_range_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
1225 {
1226   tvbuff_t *parameters_tvb;
1227 
1228   parameters_tvb = tvb_new_subset_remaining(parameter_tvb, PARAMETER_VALUE_OFFSET);
1229   dissect_parameters(parameters_tvb, pinfo, parameter_tree, NULL, NULL, NULL);
1230 }
1231 
1232 #define SMI_LENGTH 1
1233 #define SMI_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1234 
1235 static void
dissect_smi_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1236 dissect_smi_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1237 {
1238   proto_tree_add_item(parameter_tree, hf_sua_smi_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, ENC_NA);
1239   proto_tree_add_item(parameter_tree, hf_sua_smi,          parameter_tvb, SMI_OFFSET,             SMI_LENGTH,        ENC_BIG_ENDIAN);
1240   proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb,  SMI_OFFSET));
1241 }
1242 
1243 #define IMPORTANCE_LENGTH 1
1244 #define IMPORTANCE_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1245 
1246 static void
dissect_importance_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1247 dissect_importance_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1248 {
1249   proto_tree_add_item(parameter_tree, hf_sua_importance_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, ENC_NA);
1250   proto_tree_add_item(parameter_tree, hf_sua_importance,          parameter_tvb, IMPORTANCE_OFFSET,      IMPORTANCE_LENGTH, ENC_BIG_ENDIAN);
1251   proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb,  IMPORTANCE_OFFSET));
1252 }
1253 
1254 #define MESSAGE_PRIORITY_LENGTH 1
1255 #define MESSAGE_PRIORITY_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1256 
1257 static void
dissect_message_priority_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1258 dissect_message_priority_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1259 {
1260   proto_tree_add_item(parameter_tree, hf_sua_message_priority_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET,  RESERVED_3_LENGTH,       ENC_NA);
1261   proto_tree_add_item(parameter_tree, hf_sua_message_priority,          parameter_tvb, MESSAGE_PRIORITY_OFFSET, MESSAGE_PRIORITY_LENGTH, ENC_BIG_ENDIAN);
1262   proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb,  MESSAGE_PRIORITY_OFFSET));
1263 }
1264 
1265 #define PROTOCOL_CLASS_LENGTH         1
1266 #define PROTOCOL_CLASS_OFFSET         (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1267 
1268 #define RETURN_ON_ERROR_BIT_MASK 0x80
1269 #define PROTOCOL_CLASS_MASK      0x7f
1270 
1271 
1272 static const true_false_string return_on_error_bit_value = {
1273   "Return Message On Error",
1274   "No Special Options"
1275 };
1276 
1277 static void
dissect_protocol_class_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1278 dissect_protocol_class_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1279 {
1280   static int * const capabilities[] = {
1281     &hf_sua_return_on_error_bit,
1282     &hf_sua_protocol_class,
1283     NULL
1284    };
1285 
1286   proto_tree_add_item(parameter_tree, hf_sua_protocol_class_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, ENC_NA);
1287   proto_tree_add_bitmask(parameter_tree, parameter_tvb, PROTOCOL_CLASS_OFFSET, hf_sua_protocol_class_flags, ett_sua_return_on_error_bit_and_protocol_class, capabilities, ENC_BIG_ENDIAN);
1288   proto_item_append_text(parameter_item, " (%d)", tvb_get_guint8(parameter_tvb, PROTOCOL_CLASS_OFFSET) & PROTOCOL_CLASS_MASK);
1289 }
1290 
1291 #define SEQUENCE_CONTROL_LENGTH 4
1292 #define SEQUENCE_CONTROL_OFFSET PARAMETER_VALUE_OFFSET
1293 
1294 static void
dissect_sequence_control_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1295 dissect_sequence_control_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1296 {
1297   proto_tree_add_item(parameter_tree, hf_sua_sequence_control, parameter_tvb, SEQUENCE_CONTROL_OFFSET, SEQUENCE_CONTROL_LENGTH, ENC_BIG_ENDIAN);
1298   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, SEQUENCE_CONTROL_OFFSET));
1299 }
1300 
1301 #define FIRST_REMAINING_LENGTH        1
1302 #define SEGMENTATION_REFERENCE_LENGTH 3
1303 #define FIRST_REMAINING_OFFSET        PARAMETER_VALUE_OFFSET
1304 #define SEGMENTATION_REFERENCE_OFFSET (FIRST_REMAINING_OFFSET + FIRST_REMAINING_LENGTH)
1305 
1306 #define FIRST_BIT_MASK 0x80
1307 #define NUMBER_OF_SEGMENTS_MASK 0x7f
1308 
1309 static const true_false_string first_bit_value = {
1310   "First segment",
1311   "Subsequent segment"
1312 };
1313 
1314 static void
dissect_segmentation_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree)1315 dissect_segmentation_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1316 {
1317   static int * const first_remaining[] = {
1318     &hf_sua_first_bit,
1319     &hf_sua_number_of_remaining_segments,
1320     NULL
1321    };
1322 
1323   proto_tree_add_bitmask(parameter_tree, parameter_tvb, FIRST_REMAINING_OFFSET, hf_sua_first_remaining, ett_sua_first_remaining, first_remaining, ENC_BIG_ENDIAN);
1324   proto_tree_add_item(parameter_tree, hf_sua_segmentation_reference, parameter_tvb, SEGMENTATION_REFERENCE_OFFSET, SEGMENTATION_REFERENCE_LENGTH, ENC_BIG_ENDIAN);
1325 }
1326 
1327 #define CONGESTION_LEVEL_LENGTH 4
1328 #define CONGESTION_LEVEL_OFFSET PARAMETER_VALUE_OFFSET
1329 
1330 static void
dissect_congestion_level_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1331 dissect_congestion_level_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1332 {
1333   proto_tree_add_item(parameter_tree, hf_sua_congestion_level, parameter_tvb, CONGESTION_LEVEL_OFFSET, CONGESTION_LEVEL_LENGTH, ENC_BIG_ENDIAN);
1334   proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CONGESTION_LEVEL_OFFSET));
1335 }
1336 
1337 #define GTI_LENGTH               1
1338 #define NO_OF_DIGITS_LENGTH      1
1339 #define TRANSLATION_TYPE_LENGTH  1
1340 #define NUMBERING_PLAN_LENGTH    1
1341 #define NATURE_OF_ADDRESS_LENGTH 1
1342 
1343 #define GTI_OFFSET               (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1344 #define NO_OF_DIGITS_OFFSET      (GTI_OFFSET + GTI_LENGTH)
1345 #define TRANSLATION_TYPE_OFFSET  (NO_OF_DIGITS_OFFSET + NO_OF_DIGITS_LENGTH)
1346 #define NUMBERING_PLAN_OFFSET    (TRANSLATION_TYPE_OFFSET + TRANSLATION_TYPE_LENGTH)
1347 #define NATURE_OF_ADDRESS_OFFSET (NUMBERING_PLAN_OFFSET + NUMBERING_PLAN_LENGTH)
1348 #define GLOBAL_TITLE_OFFSET      (NATURE_OF_ADDRESS_OFFSET + NATURE_OF_ADDRESS_LENGTH)
1349 
1350 #define ISDN_TELEPHONY_NUMBERING_PLAN   1
1351 #define GENERIC_NUMBERING_PLAN          2
1352 #define DATA_NUMBERING_PLAN             3
1353 #define TELEX_NUMBERING_PLAN            4
1354 #define MARITIME_MOBILE_NUMBERING_PLAN  5
1355 #define LAND_MOBILE_NUMBERING_PLAN      6
1356 #define ISDN_MOBILE_NUMBERING_PLAN      7
1357 #define PRIVATE_NETWORK_NUMBERING_PLAN 14
1358 
1359 static const value_string numbering_plan_values[] = {
1360   { ISDN_TELEPHONY_NUMBERING_PLAN,  "ISDN/Telephony Numbering Plan (Rec. E.161 and E.164)" },
1361   { GENERIC_NUMBERING_PLAN,         "Generic Numbering Plan" },
1362   { DATA_NUMBERING_PLAN,            "Data Numbering Plan (Rec. X.121)" },
1363   { TELEX_NUMBERING_PLAN,           "Telex Numbering Plan (Rec. F.69)" },
1364   { MARITIME_MOBILE_NUMBERING_PLAN, "Maritime Mobile Numbering Plan (Rec. E.210 and E.211)" },
1365   { LAND_MOBILE_NUMBERING_PLAN,     "Land Mobile Numbering Plan (Rec. E.212)" },
1366   { ISDN_MOBILE_NUMBERING_PLAN,     "ISDN/Mobile Numbering Plan (Rec. E.214)" },
1367   { PRIVATE_NETWORK_NUMBERING_PLAN, "Private Network Or Network-Specific Numbering Plan" },
1368   { 0,                                             NULL } };
1369 
1370 #define UNKNOWN_NATURE_OF_ADDRESS                       0
1371 #define SUBSCRIBER_NUMBER_NATURE_OF_ADDRESS             1
1372 #define RESERVED_FOR_NATIONAL_USE_NATURE_OF_ADDRESS     2
1373 #define NATIONAL_SIGNIFICANT_NUMBER_NATURE_OF_ADDRESS   3
1374 #define INTERNATION_NUMBER_NATURE_OF_ADDRESS            4
1375 
1376 static const value_string nature_of_address_values[] = {
1377   { UNKNOWN_NATURE_OF_ADDRESS,                     "Unknown" },
1378   { SUBSCRIBER_NUMBER_NATURE_OF_ADDRESS,           "Subscriber Number" },
1379   { RESERVED_FOR_NATIONAL_USE_NATURE_OF_ADDRESS,   "Reserved For National Use" },
1380   { NATIONAL_SIGNIFICANT_NUMBER_NATURE_OF_ADDRESS, "National Significant Number" },
1381   { INTERNATION_NUMBER_NATURE_OF_ADDRESS,          "International Number" },
1382   { 0,                                             NULL } };
1383 
1384 static void
dissect_global_title_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,gboolean source)1385 dissect_global_title_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, gboolean source)
1386 {
1387   guint16 global_title_length;
1388   guint16 offset;
1389   gboolean even_length;
1390   guint8 odd_signal, even_signal;
1391   guint8 number_of_digits;
1392   char *gt_digits;
1393 
1394   gt_digits = (char *)wmem_alloc0(wmem_packet_scope(), GT_MAX_SIGNALS+1);
1395 
1396   global_title_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) -
1397                         (PARAMETER_HEADER_LENGTH + RESERVED_3_LENGTH + GTI_LENGTH + NO_OF_DIGITS_LENGTH + TRANSLATION_TYPE_LENGTH + NUMBERING_PLAN_LENGTH + NATURE_OF_ADDRESS_LENGTH);
1398   proto_tree_add_item(parameter_tree, source ? hf_sua_source_gt_reserved       : hf_sua_dest_gt_reserved,       parameter_tvb, PARAMETER_VALUE_OFFSET,   RESERVED_3_LENGTH,        ENC_NA);
1399   proto_tree_add_item(parameter_tree, source ? hf_sua_source_gti               : hf_sua_dest_gti,               parameter_tvb, GTI_OFFSET,               GTI_LENGTH,               ENC_BIG_ENDIAN);
1400   proto_tree_add_item(parameter_tree, source ? hf_sua_source_number_of_digits  : hf_sua_dest_number_of_digits,  parameter_tvb, NO_OF_DIGITS_OFFSET,      NO_OF_DIGITS_LENGTH,      ENC_BIG_ENDIAN);
1401   proto_tree_add_item(parameter_tree, source ? hf_sua_source_translation_type  : hf_sua_dest_translation_type,  parameter_tvb, TRANSLATION_TYPE_OFFSET,  TRANSLATION_TYPE_LENGTH,  ENC_BIG_ENDIAN);
1402   proto_tree_add_item(parameter_tree, source ? hf_sua_source_numbering_plan    : hf_sua_dest_numbering_plan,    parameter_tvb, NUMBERING_PLAN_OFFSET,    NUMBERING_PLAN_LENGTH,    ENC_BIG_ENDIAN);
1403   proto_tree_add_item(parameter_tree, source ? hf_sua_source_nature_of_address : hf_sua_dest_nature_of_address, parameter_tvb, NATURE_OF_ADDRESS_OFFSET, NATURE_OF_ADDRESS_LENGTH, ENC_BIG_ENDIAN);
1404 
1405   number_of_digits = tvb_get_guint8(parameter_tvb, NO_OF_DIGITS_OFFSET);
1406   even_length = !(number_of_digits % 2);
1407   offset = GLOBAL_TITLE_OFFSET;
1408 
1409   while(offset < GLOBAL_TITLE_OFFSET + global_title_length) {
1410     odd_signal = tvb_get_guint8(parameter_tvb, offset) & GT_ODD_SIGNAL_MASK;
1411     even_signal = tvb_get_guint8(parameter_tvb, offset) & GT_EVEN_SIGNAL_MASK;
1412     even_signal >>= GT_EVEN_SIGNAL_SHIFT;
1413 
1414     (void) g_strlcat(gt_digits, val_to_str_const(odd_signal, sccp_address_signal_values,
1415                                           "Unknown"), GT_MAX_SIGNALS+1);
1416 
1417     /* If the last signal is NOT filler */
1418     if (offset != (GLOBAL_TITLE_OFFSET + global_title_length - 1) || even_length == TRUE)
1419       (void) g_strlcat(gt_digits, val_to_str_const(even_signal, sccp_address_signal_values,
1420                                             "Unknown"), GT_MAX_SIGNALS+1);
1421 
1422     offset += GT_SIGNAL_LENGTH;
1423   }
1424 
1425   proto_tree_add_string_format(parameter_tree, source ? hf_sua_source_global_title_digits : hf_sua_dest_global_title_digits,
1426                                parameter_tvb, GLOBAL_TITLE_OFFSET,
1427                                global_title_length, gt_digits,
1428                                "Address information (digits): %s", gt_digits);
1429 
1430   if (sua_ri == ROUTE_ON_GT_ROUTING_INDICATOR) {
1431     if (source) {
1432       sua_source_gt = gt_digits;
1433     } else {
1434       sua_destination_gt = gt_digits;
1435     }
1436   }
1437 }
1438 
1439 #define POINT_CODE_LENGTH 4
1440 #define POINT_CODE_OFFSET PARAMETER_VALUE_OFFSET
1441 
1442 static void
dissect_point_code_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item,gboolean source)1443 dissect_point_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, gboolean source)
1444 {
1445   guint32 pc;
1446 
1447   pc = tvb_get_ntohl(parameter_tvb, POINT_CODE_OFFSET);
1448 
1449   if (sua_ri == ROUTE_ON_SSN_PC_ROUTING_INDICATOR) {
1450     if (source) {
1451       sua_opc->type = (Standard_Type)mtp3_standard;
1452       sua_opc->pc = pc;
1453     } else {
1454       sua_dpc->type = (Standard_Type)mtp3_standard;
1455       sua_dpc->pc = pc;
1456     }
1457   }
1458 
1459   proto_tree_add_item(parameter_tree, source ? hf_sua_source_point_code : hf_sua_dest_point_code, parameter_tvb, POINT_CODE_OFFSET, POINT_CODE_LENGTH, ENC_BIG_ENDIAN);
1460   proto_item_append_text(parameter_item, " (%s)", mtp3_pc_to_str(pc));
1461 }
1462 
1463 #define SSN_LENGTH 1
1464 #define SSN_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
1465 #define INVALID_SSN 0xff
1466 
1467 static void
dissect_ssn_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item,guint8 * ssn,gboolean source)1468 dissect_ssn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, guint8 *ssn, gboolean source)
1469 {
1470   *ssn = tvb_get_guint8(parameter_tvb,  SSN_OFFSET);
1471 
1472   if(parameter_tree) {
1473     proto_tree_add_item(parameter_tree, source ? hf_sua_source_ssn_reserved : hf_sua_dest_ssn_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, ENC_NA);
1474     proto_tree_add_item(parameter_tree, source ? hf_sua_source_ssn_number   : hf_sua_dest_ssn_number,   parameter_tvb, SSN_OFFSET,             SSN_LENGTH,        ENC_BIG_ENDIAN);
1475     proto_item_append_text(parameter_item, " (%u)", *ssn);
1476   }
1477 }
1478 
1479 #define IPV4_ADDRESS_LENGTH 4
1480 #define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
1481 
1482 static void
dissect_ipv4_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item,gboolean source)1483 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, gboolean source)
1484 {
1485   proto_tree_add_item(parameter_tree, source ? hf_sua_source_ipv4 : hf_sua_dest_ipv4, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, ENC_BIG_ENDIAN);
1486   proto_item_append_text(parameter_item, " (%s)", tvb_ip_to_str(wmem_packet_scope(), parameter_tvb, IPV4_ADDRESS_OFFSET));
1487 }
1488 
1489 #define HOSTNAME_OFFSET PARAMETER_VALUE_OFFSET
1490 
1491 static void
dissect_hostname_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item,gboolean source)1492 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, gboolean source)
1493 {
1494   guint16 hostname_length;
1495 
1496   hostname_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1497   proto_tree_add_item(parameter_tree, source ? hf_sua_source_hostname : hf_sua_dest_hostname, parameter_tvb, HOSTNAME_OFFSET, hostname_length, ENC_ASCII|ENC_NA);
1498   proto_item_append_text(parameter_item, " (%.*s)", hostname_length,
1499                          tvb_format_text(wmem_packet_scope(), parameter_tvb, HOSTNAME_OFFSET, hostname_length));
1500 }
1501 
1502 #define IPV6_ADDRESS_LENGTH 16
1503 #define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
1504 
1505 static void
dissect_ipv6_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item,gboolean source)1506 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, gboolean source)
1507 {
1508   proto_tree_add_item(parameter_tree, source ? hf_sua_source_ipv6 : hf_sua_dest_ipv6, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, ENC_NA);
1509   proto_item_append_text(parameter_item, " (%s)", tvb_ip6_to_str(wmem_packet_scope(), parameter_tvb, IPV6_ADDRESS_OFFSET));
1510 }
1511 
1512 static void
dissect_unknown_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1513 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1514 {
1515   guint16 parameter_value_length;
1516 
1517   parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1518   proto_tree_add_item(parameter_tree, hf_sua_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, ENC_NA);
1519   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"));
1520 }
1521 
1522 #define V8_DATA_PARAMETER_TAG                         0x0003
1523 #define V8_INFO_STRING_PARAMETER_TAG                  0x0004
1524 #define V8_ROUTING_CONTEXT_PARAMETER_TAG              0x0006
1525 #define V8_DIAGNOSTIC_INFO_PARAMETER_TAG              0x0007
1526 #define V8_HEARTBEAT_DATA_PARAMETER_TAG               0x0009
1527 #define V8_TRAFFIC_MODE_TYPE_PARAMETER_TAG            0x000b
1528 #define V8_ERROR_CODE_PARAMETER_TAG                   0x000c
1529 #define V8_STATUS_PARAMETER_TAG                       0x000d
1530 #define V8_CONGESTION_LEVEL_PARAMETER_TAG             0x000f
1531 #define V8_ASP_IDENTIFIER_PARAMETER_TAG               0x0011
1532 #define V8_AFFECTED_POINT_CODE_PARAMETER_TAG          0x0012
1533 
1534 #define V8_SS7_HOP_COUNTER_PARAMETER_TAG              0x0101
1535 #define V8_SOURCE_ADDRESS_PARAMETER_TAG               0x0102
1536 #define V8_DESTINATION_ADDRESS_PARAMETER_TAG          0x0103
1537 #define V8_SOURCE_REFERENCE_NUMBER_PARAMETER_TAG      0x0104
1538 #define V8_DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG 0x0105
1539 #define V8_SCCP_CAUSE_PARAMETER_TAG                   0x0106
1540 #define V8_SEQUENCE_NUMBER_PARAMETER_TAG              0x0107
1541 #define V8_RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG      0x0108
1542 #define V8_ASP_CAPABILITIES_PARAMETER_TAG             0x0109
1543 #define V8_CREDIT_PARAMETER_TAG                       0x010a
1544 #define V8_USER_CAUSE_PARAMETER_TAG                   0x010c
1545 #define V8_NETWORK_APPEARANCE_PARAMETER_TAG           0x010d
1546 #define V8_ROUTING_KEY_PARAMETER_TAG                  0x010e
1547 #define V8_REGISTRATION_RESULT_PARAMETER_TAG          0x010f
1548 #define V8_DEREGISTRATION_RESULT_PARAMETER_TAG        0x0110
1549 #define V8_ADDRESS_RANGE_PARAMETER_TAG                0x0111
1550 #define V8_CORRELATION_ID_PARAMETER_TAG               0x0112
1551 #define V8_IMPORTANCE_PARAMETER_TAG                   0x0113
1552 #define V8_MESSAGE_PRIORITY_PARAMETER_TAG             0x0114
1553 #define V8_PROTOCOL_CLASS_PARAMETER_TAG               0x0115
1554 #define V8_SEQUENCE_CONTROL_PARAMETER_TAG             0x0116
1555 #define V8_SEGMENTATION_PARAMETER_TAG                 0x0117
1556 #define V8_SMI_PARAMETER_TAG                          0x0118
1557 #define V8_TID_LABEL_PARAMETER_TAG                    0x0119
1558 #define V8_DRN_LABEL_PARAMETER_TAG                    0x011a
1559 
1560 #define V8_GLOBAL_TITLE_PARAMETER_TAG                 0x8001
1561 #define V8_POINT_CODE_PARAMETER_TAG                   0x8002
1562 #define V8_SUBSYSTEM_NUMBER_PARAMETER_TAG             0x8003
1563 #define V8_IPV4_ADDRESS_PARAMETER_TAG                 0x8004
1564 #define V8_HOSTNAME_PARAMETER_TAG                     0x8005
1565 #define V8_IPV6_ADDRESS_PARAMETER_TAG                 0x8006
1566 
1567 static const value_string v8_parameter_tag_values[] = {
1568   { V8_DATA_PARAMETER_TAG,                         "Data" },
1569   { V8_INFO_STRING_PARAMETER_TAG,                  "Info String" },
1570   { V8_ROUTING_CONTEXT_PARAMETER_TAG,              "Routing context" },
1571   { V8_DIAGNOSTIC_INFO_PARAMETER_TAG,              "Diagnostic info" },
1572   { V8_HEARTBEAT_DATA_PARAMETER_TAG,               "Heartbeat data" },
1573   { V8_TRAFFIC_MODE_TYPE_PARAMETER_TAG,            "Traffic mode type" },
1574   { V8_ERROR_CODE_PARAMETER_TAG,                   "Error code" },
1575   { V8_STATUS_PARAMETER_TAG,                       "Status" },
1576   { V8_CONGESTION_LEVEL_PARAMETER_TAG,             "Congestion level" },
1577   { V8_ASP_IDENTIFIER_PARAMETER_TAG,               "ASP identifier" },
1578   { V8_AFFECTED_POINT_CODE_PARAMETER_TAG,          "Affected point code" },
1579   { V8_SS7_HOP_COUNTER_PARAMETER_TAG,              "SS7 hop counter" },
1580   { V8_SOURCE_ADDRESS_PARAMETER_TAG,               "Source address" },
1581   { V8_DESTINATION_ADDRESS_PARAMETER_TAG,          "Destination address" },
1582   { V8_SOURCE_REFERENCE_NUMBER_PARAMETER_TAG,      "Source reference number" },
1583   { V8_DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG, "Destination reference number" },
1584   { V8_SCCP_CAUSE_PARAMETER_TAG,                   "SCCP cause" },
1585   { V8_SEQUENCE_NUMBER_PARAMETER_TAG,              "Sequence number" },
1586   { V8_RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG,      "Receive sequence number" },
1587   { V8_ASP_CAPABILITIES_PARAMETER_TAG,             "ASP capabilities" },
1588   { V8_CREDIT_PARAMETER_TAG,                       "Credit" },
1589   { V8_USER_CAUSE_PARAMETER_TAG,                   "User/Cause" },
1590   { V8_NETWORK_APPEARANCE_PARAMETER_TAG,           "Network appearance" },
1591   { V8_ROUTING_KEY_PARAMETER_TAG,                  "Routing key" },
1592   { V8_REGISTRATION_RESULT_PARAMETER_TAG,          "Registration result" },
1593   { V8_DEREGISTRATION_RESULT_PARAMETER_TAG,        "Deregistration result" },
1594   { V8_ADDRESS_RANGE_PARAMETER_TAG,                "Address range" },
1595   { V8_CORRELATION_ID_PARAMETER_TAG,               "Correlation ID" },
1596   { V8_IMPORTANCE_PARAMETER_TAG,                   "Importance" },
1597   { V8_MESSAGE_PRIORITY_PARAMETER_TAG,             "Message priority" },
1598   { V8_PROTOCOL_CLASS_PARAMETER_TAG,               "Protocol class" },
1599   { V8_SEQUENCE_CONTROL_PARAMETER_TAG,             "Sequence control" },
1600   { V8_SEGMENTATION_PARAMETER_TAG,                 "Segmentation" },
1601   { V8_SMI_PARAMETER_TAG,                          "SMI" },
1602   { V8_TID_LABEL_PARAMETER_TAG,                    "TID label" },
1603   { V8_DRN_LABEL_PARAMETER_TAG,                    "DRN label" },
1604   { V8_GLOBAL_TITLE_PARAMETER_TAG,                 "Global title" },
1605   { V8_POINT_CODE_PARAMETER_TAG,                   "Point code" },
1606   { V8_SUBSYSTEM_NUMBER_PARAMETER_TAG,             "Subsystem number" },
1607   { V8_IPV4_ADDRESS_PARAMETER_TAG,                 "IPv4 address" },
1608   { V8_HOSTNAME_PARAMETER_TAG,                     "Hostname" },
1609   { V8_IPV6_ADDRESS_PARAMETER_TAG,                 "IPv6 address" },
1610   { 0,                                          NULL } };
1611 
1612 static void
dissect_v8_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * tree,tvbuff_t ** data_tvb,guint8 * source_ssn,guint8 * dest_ssn)1613 dissect_v8_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn)
1614 {
1615   guint16 tag, length, padding_length;
1616   proto_item *parameter_item;
1617   proto_tree *parameter_tree;
1618   guint8 ssn = INVALID_SSN;
1619 
1620   /* extract tag and length from the parameter */
1621   tag            = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
1622   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1623   padding_length = tvb_reported_length(parameter_tvb) - length;
1624 
1625   /* create proto_tree stuff */
1626   parameter_tree = proto_tree_add_subtree(tree, parameter_tvb, PARAMETER_HEADER_OFFSET, -1, ett_sua_parameter, &parameter_item, val_to_str_const(tag, v8_parameter_tag_values, "Unknown parameter"));
1627 
1628   /* add tag and length to the sua tree */
1629   proto_tree_add_item(parameter_tree, hf_sua_v8_parameter_tag,    parameter_tvb, PARAMETER_TAG_OFFSET,    PARAMETER_TAG_LENGTH,    ENC_BIG_ENDIAN);
1630   proto_tree_add_item(parameter_tree, hf_sua_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, ENC_BIG_ENDIAN);
1631 
1632   /*
1633   ** If no tree, only the data and ssn parameters in the source and destination
1634   ** address need to be dissected. This in order to make dissection of the data
1635   ** possible when there is no tree.
1636   */
1637   if (!tree && tag != V8_DATA_PARAMETER_TAG
1638             && tag != V8_SOURCE_ADDRESS_PARAMETER_TAG
1639             && tag != V8_DESTINATION_ADDRESS_PARAMETER_TAG
1640             && tag != V8_DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG
1641             && tag != V8_SOURCE_REFERENCE_NUMBER_PARAMETER_TAG
1642             && tag != V8_SUBSYSTEM_NUMBER_PARAMETER_TAG)
1643     return;
1644 
1645   switch(tag) {
1646   case V8_DATA_PARAMETER_TAG:
1647     dissect_data_parameter(parameter_tvb, parameter_tree, parameter_item, data_tvb);
1648     break;
1649   case V8_INFO_STRING_PARAMETER_TAG:
1650     dissect_info_string_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1651     break;
1652   case V8_ROUTING_CONTEXT_PARAMETER_TAG:
1653     dissect_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
1654     break;
1655   case V8_DIAGNOSTIC_INFO_PARAMETER_TAG:
1656     dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
1657     break;
1658   case V8_HEARTBEAT_DATA_PARAMETER_TAG:
1659     dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
1660     break;
1661   case V8_TRAFFIC_MODE_TYPE_PARAMETER_TAG:
1662     dissect_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1663     break;
1664   case V8_ERROR_CODE_PARAMETER_TAG:
1665     dissect_v8_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1666     break;
1667   case V8_STATUS_PARAMETER_TAG:
1668     dissect_status_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1669     break;
1670   case V8_CONGESTION_LEVEL_PARAMETER_TAG:
1671     dissect_congestion_level_parameter(parameter_tvb, parameter_tree, parameter_item);
1672     break;
1673   case V8_ASP_IDENTIFIER_PARAMETER_TAG:
1674     dissect_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1675     break;
1676   case V8_AFFECTED_POINT_CODE_PARAMETER_TAG:
1677     dissect_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
1678     break;
1679   case V8_SS7_HOP_COUNTER_PARAMETER_TAG:
1680     dissect_ss7_hop_counter_parameter(parameter_tvb, parameter_tree, parameter_item);
1681     break;
1682   case V8_SOURCE_ADDRESS_PARAMETER_TAG:
1683     dissect_source_address_parameter(parameter_tvb, pinfo, parameter_tree, source_ssn);
1684     break;
1685   case V8_DESTINATION_ADDRESS_PARAMETER_TAG:
1686     dissect_destination_address_parameter(parameter_tvb, pinfo, parameter_tree, dest_ssn);
1687     break;
1688   case V8_SOURCE_REFERENCE_NUMBER_PARAMETER_TAG:
1689     dissect_source_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1690     break;
1691   case V8_DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG:
1692     dissect_destination_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1693     break;
1694   case V8_SCCP_CAUSE_PARAMETER_TAG:
1695     dissect_sccp_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
1696     break;
1697   case V8_SEQUENCE_NUMBER_PARAMETER_TAG:
1698     dissect_sequence_number_parameter(parameter_tvb, parameter_tree);
1699     break;
1700   case V8_RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG:
1701     dissect_receive_sequence_number_parameter(parameter_tvb, parameter_tree);
1702     break;
1703   case V8_ASP_CAPABILITIES_PARAMETER_TAG:
1704     dissect_asp_capabilities_parameter(parameter_tvb, parameter_tree);
1705     break;
1706   case V8_CREDIT_PARAMETER_TAG:
1707     dissect_credit_parameter(parameter_tvb, parameter_tree, parameter_item);
1708     break;
1709   case V8_USER_CAUSE_PARAMETER_TAG:
1710     dissect_user_cause_parameter(parameter_tvb, parameter_tree);
1711     break;
1712   case V8_NETWORK_APPEARANCE_PARAMETER_TAG:
1713     dissect_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
1714     break;
1715   case V8_ROUTING_KEY_PARAMETER_TAG:
1716     dissect_routing_key_parameter(parameter_tvb, pinfo, parameter_tree);
1717     break;
1718   case V8_REGISTRATION_RESULT_PARAMETER_TAG:
1719     dissect_registration_result_parameter(parameter_tvb, pinfo, parameter_tree);
1720     break;
1721   case V8_DEREGISTRATION_RESULT_PARAMETER_TAG:
1722     dissect_deregistration_result_parameter(parameter_tvb, pinfo, parameter_tree);
1723     break;
1724   case V8_ADDRESS_RANGE_PARAMETER_TAG:
1725     dissect_address_range_parameter(parameter_tvb, pinfo, parameter_tree);
1726     break;
1727   case V8_CORRELATION_ID_PARAMETER_TAG:
1728     dissect_correlation_id_parameter(parameter_tvb, parameter_tree, parameter_item);
1729     break;
1730   case V8_IMPORTANCE_PARAMETER_TAG:
1731     dissect_importance_parameter(parameter_tvb, parameter_tree, parameter_item);
1732     break;
1733   case V8_MESSAGE_PRIORITY_PARAMETER_TAG:
1734     dissect_message_priority_parameter(parameter_tvb, parameter_tree, parameter_item);
1735     break;
1736   case V8_PROTOCOL_CLASS_PARAMETER_TAG:
1737     dissect_protocol_class_parameter(parameter_tvb, parameter_tree, parameter_item);
1738     break;
1739   case V8_SEQUENCE_CONTROL_PARAMETER_TAG:
1740     dissect_sequence_control_parameter(parameter_tvb, parameter_tree, parameter_item);
1741     break;
1742   case V8_SEGMENTATION_PARAMETER_TAG:
1743     dissect_segmentation_parameter(parameter_tvb, parameter_tree);
1744     break;
1745   case V8_SMI_PARAMETER_TAG:
1746     dissect_smi_parameter(parameter_tvb, parameter_tree, parameter_item);
1747     break;
1748   case V8_TID_LABEL_PARAMETER_TAG:
1749     dissect_tid_label_parameter(parameter_tvb, parameter_tree);
1750     break;
1751   case V8_DRN_LABEL_PARAMETER_TAG:
1752     dissect_drn_label_parameter(parameter_tvb, parameter_tree);
1753     break;
1754   case V8_GLOBAL_TITLE_PARAMETER_TAG:
1755     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
1756     dissect_global_title_parameter(parameter_tvb, parameter_tree, (source_ssn != NULL));
1757     break;
1758   case V8_POINT_CODE_PARAMETER_TAG:
1759     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
1760     dissect_point_code_parameter(parameter_tvb, parameter_tree, parameter_item, (source_ssn != NULL));
1761     break;
1762   case V8_SUBSYSTEM_NUMBER_PARAMETER_TAG:
1763     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
1764     dissect_ssn_parameter(parameter_tvb, parameter_tree, parameter_item, &ssn, (source_ssn != NULL));
1765     if(source_ssn)
1766     {
1767         *source_ssn = ssn;
1768     }
1769     if(dest_ssn)
1770     {
1771         *dest_ssn = ssn;
1772     }
1773     break;
1774   case V8_IPV4_ADDRESS_PARAMETER_TAG:
1775     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
1776     dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item, (source_ssn != NULL));
1777     break;
1778   case V8_HOSTNAME_PARAMETER_TAG:
1779     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
1780     dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item, (source_ssn != NULL));
1781     break;
1782   case V8_IPV6_ADDRESS_PARAMETER_TAG:
1783     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
1784     dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item, (source_ssn != NULL));
1785     break;
1786   default:
1787     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1788     break;
1789   };
1790   if (parameter_tree && (padding_length > 0))
1791     proto_tree_add_item(parameter_tree, hf_sua_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, ENC_NA);
1792 }
1793 
1794 #define INFO_STRING_PARAMETER_TAG                  0x0004
1795 #define ROUTING_CONTEXT_PARAMETER_TAG              0x0006
1796 #define DIAGNOSTIC_INFO_PARAMETER_TAG              0x0007
1797 #define HEARTBEAT_DATA_PARAMETER_TAG               0x0009
1798 #define TRAFFIC_MODE_TYPE_PARAMETER_TAG            0x000b
1799 #define ERROR_CODE_PARAMETER_TAG                   0x000c
1800 #define STATUS_PARAMETER_TAG                       0x000d
1801 #define ASP_IDENTIFIER_PARAMETER_TAG               0x0011
1802 #define AFFECTED_POINT_CODE_PARAMETER_TAG          0x0012
1803 #define CORRELATION_ID_PARAMETER_TAG               0x0013
1804 #define REGISTRATION_RESULT_PARAMETER_TAG          0x0014
1805 #define DEREGISTRATION_RESULT_PARAMETER_TAG        0x0015
1806 #define REGISTRATION_STATUS_PARAMETER_TAG          0x0016
1807 #define DEREGISTRATION_STATUS_PARAMETER_TAG        0x0017
1808 #define LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG 0x0018
1809 
1810 #define SS7_HOP_COUNTER_PARAMETER_TAG              0x0101
1811 #define SOURCE_ADDRESS_PARAMETER_TAG               0x0102
1812 #define DESTINATION_ADDRESS_PARAMETER_TAG          0x0103
1813 #define SOURCE_REFERENCE_NUMBER_PARAMETER_TAG      0x0104
1814 #define DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG 0x0105
1815 #define SCCP_CAUSE_PARAMETER_TAG                   0x0106
1816 #define SEQUENCE_NUMBER_PARAMETER_TAG              0x0107
1817 #define RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG      0x0108
1818 #define ASP_CAPABILITIES_PARAMETER_TAG             0x0109
1819 #define CREDIT_PARAMETER_TAG                       0x010a
1820 #define DATA_PARAMETER_TAG                         0x010b
1821 #define USER_CAUSE_PARAMETER_TAG                   0x010c
1822 #define NETWORK_APPEARANCE_PARAMETER_TAG           0x010d
1823 #define ROUTING_KEY_PARAMETER_TAG                  0x010e
1824 #define DRN_LABEL_PARAMETER_TAG                    0x010f
1825 #define TID_LABEL_PARAMETER_TAG                    0x0110
1826 #define ADDRESS_RANGE_PARAMETER_TAG                0x0111
1827 #define SMI_PARAMETER_TAG                          0x0112
1828 #define IMPORTANCE_PARAMETER_TAG                   0x0113
1829 #define MESSAGE_PRIORITY_PARAMETER_TAG             0x0114
1830 #define PROTOCOL_CLASS_PARAMETER_TAG               0x0115
1831 #define SEQUENCE_CONTROL_PARAMETER_TAG             0x0116
1832 #define SEGMENTATION_PARAMETER_TAG                 0x0117
1833 #define CONGESTION_LEVEL_PARAMETER_TAG             0x0118
1834 
1835 #define GLOBAL_TITLE_PARAMETER_TAG                 0x8001
1836 #define POINT_CODE_PARAMETER_TAG                   0x8002
1837 #define SUBSYSTEM_NUMBER_PARAMETER_TAG             0x8003
1838 #define IPV4_ADDRESS_PARAMETER_TAG                 0x8004
1839 #define HOSTNAME_PARAMETER_TAG                     0x8005
1840 #define IPV6_ADDRESS_PARAMETER_TAG                 0x8006
1841 
1842 static const value_string parameter_tag_values[] = {
1843   { INFO_STRING_PARAMETER_TAG,                  "Info String" },
1844   { ROUTING_CONTEXT_PARAMETER_TAG,              "Routing context" },
1845   { DIAGNOSTIC_INFO_PARAMETER_TAG,              "Diagnostic info" },
1846   { HEARTBEAT_DATA_PARAMETER_TAG,               "Heartbeat data" },
1847   { TRAFFIC_MODE_TYPE_PARAMETER_TAG,            "Traffic mode type" },
1848   { ERROR_CODE_PARAMETER_TAG,                   "Error code" },
1849   { STATUS_PARAMETER_TAG,                       "Status" },
1850   { ASP_IDENTIFIER_PARAMETER_TAG,               "ASP identifier" },
1851   { AFFECTED_POINT_CODE_PARAMETER_TAG,          "Affected point code" },
1852   { CORRELATION_ID_PARAMETER_TAG,               "Correlation ID" },
1853   { REGISTRATION_RESULT_PARAMETER_TAG,          "Registration result" },
1854   { DEREGISTRATION_RESULT_PARAMETER_TAG,        "Deregistration result" },
1855   { REGISTRATION_STATUS_PARAMETER_TAG,          "Registration status" },
1856   { DEREGISTRATION_STATUS_PARAMETER_TAG,        "Deregistration status" },
1857   { LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG, "Local routing key identifier" },
1858   { SS7_HOP_COUNTER_PARAMETER_TAG,              "SS7 hop counter" },
1859   { SOURCE_ADDRESS_PARAMETER_TAG,               "Source address" },
1860   { DESTINATION_ADDRESS_PARAMETER_TAG,          "Destination address" },
1861   { SOURCE_REFERENCE_NUMBER_PARAMETER_TAG,      "Source reference number" },
1862   { DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG, "Destination reference number" },
1863   { SCCP_CAUSE_PARAMETER_TAG,                   "SCCP cause" },
1864   { SEQUENCE_NUMBER_PARAMETER_TAG,              "Sequence number" },
1865   { RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG,      "Receive sequence number" },
1866   { ASP_CAPABILITIES_PARAMETER_TAG,             "ASP capabilities" },
1867   { CREDIT_PARAMETER_TAG,                       "Credit" },
1868   { DATA_PARAMETER_TAG,                         "Data" },
1869   { USER_CAUSE_PARAMETER_TAG,                   "User/Cause" },
1870   { NETWORK_APPEARANCE_PARAMETER_TAG,           "Network appearance" },
1871   { ROUTING_KEY_PARAMETER_TAG,                  "Routing key" },
1872   { DRN_LABEL_PARAMETER_TAG,                    "DRN label" },
1873   { TID_LABEL_PARAMETER_TAG,                    "TID label" },
1874   { ADDRESS_RANGE_PARAMETER_TAG,                "Address range" },
1875   { SMI_PARAMETER_TAG,                          "SMI" },
1876   { IMPORTANCE_PARAMETER_TAG,                   "Importance" },
1877   { MESSAGE_PRIORITY_PARAMETER_TAG,             "Message priority" },
1878   { PROTOCOL_CLASS_PARAMETER_TAG,               "Protocol class" },
1879   { SEQUENCE_CONTROL_PARAMETER_TAG,             "Sequence control" },
1880   { SEGMENTATION_PARAMETER_TAG,                 "Segmentation" },
1881   { CONGESTION_LEVEL_PARAMETER_TAG,             "Congestion level" },
1882   { GLOBAL_TITLE_PARAMETER_TAG,                 "Global title" },
1883   { POINT_CODE_PARAMETER_TAG,                   "Point code" },
1884   { SUBSYSTEM_NUMBER_PARAMETER_TAG,             "Subsystem number" },
1885   { IPV4_ADDRESS_PARAMETER_TAG,                 "IPv4 address" },
1886   { HOSTNAME_PARAMETER_TAG,                     "Hostname" },
1887   { IPV6_ADDRESS_PARAMETER_TAG,                 "IPv6 address" },
1888   { 0,                                          NULL } };
1889 
1890 static void
dissect_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * tree,tvbuff_t ** data_tvb,guint8 * source_ssn,guint8 * dest_ssn)1891 dissect_parameter(tvbuff_t *parameter_tvb,  packet_info *pinfo, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn)
1892 {
1893   guint16 tag, length, padding_length;
1894   proto_item *parameter_item;
1895   proto_tree *parameter_tree;
1896   guint8 ssn = INVALID_SSN;
1897   const gchar *param_tag_str = NULL;
1898 
1899   /* Extract tag and length from the parameter */
1900   tag            = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
1901   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1902   padding_length = tvb_reported_length(parameter_tvb) - length;
1903 
1904   /* Create proto_tree stuff */
1905   /* If it's a known parameter it's present in the value_string.
1906    * If param_tag_str = NULL then this is an unknown parameter
1907    */
1908   param_tag_str    = try_val_to_str(tag, parameter_tag_values);
1909   if(param_tag_str) {
1910     /* The parameter exists */
1911     parameter_tree = proto_tree_add_subtree(tree, parameter_tvb, PARAMETER_HEADER_OFFSET, -1, ett_sua_parameter, &parameter_item, param_tag_str);
1912   } else {
1913     if(dissector_try_uint(sua_parameter_table, tag, parameter_tvb, pinfo,tree)) {
1914        return;
1915     }
1916 
1917     parameter_tree = proto_tree_add_subtree(tree, parameter_tvb, PARAMETER_HEADER_OFFSET, -1, ett_sua_parameter, &parameter_item, "Unknown parameter");
1918   }
1919 
1920   /* Add tag and length to the sua tree */
1921   proto_tree_add_item(parameter_tree, hf_sua_parameter_tag,    parameter_tvb, PARAMETER_TAG_OFFSET,    PARAMETER_TAG_LENGTH,    ENC_BIG_ENDIAN);
1922   proto_tree_add_item(parameter_tree, hf_sua_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, ENC_BIG_ENDIAN);
1923 
1924   /*
1925   ** If no tree, only the data, ssn, PC, and GT parameters in the source and destination
1926   ** addresses need to be dissected. This in order to make dissection of the data
1927   ** possible and to allow us to set the source and destination addresses when there is
1928   ** no tree.
1929   */
1930   if (!tree && tag != DATA_PARAMETER_TAG
1931             && tag != SOURCE_ADDRESS_PARAMETER_TAG
1932             && tag != DESTINATION_ADDRESS_PARAMETER_TAG
1933             && tag != POINT_CODE_PARAMETER_TAG
1934             && tag != GLOBAL_TITLE_PARAMETER_TAG
1935             && tag != DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG
1936             && tag != SOURCE_REFERENCE_NUMBER_PARAMETER_TAG
1937             && tag != SUBSYSTEM_NUMBER_PARAMETER_TAG)
1938     return;   /* Nothing to do here */
1939 
1940   switch(tag) {
1941   case DATA_PARAMETER_TAG:
1942     dissect_data_parameter(parameter_tvb, parameter_tree, parameter_item, data_tvb);
1943     break;
1944   case INFO_STRING_PARAMETER_TAG:
1945     dissect_info_string_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1946     break;
1947   case ROUTING_CONTEXT_PARAMETER_TAG:
1948     dissect_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
1949     break;
1950   case DIAGNOSTIC_INFO_PARAMETER_TAG:
1951     dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
1952     break;
1953   case HEARTBEAT_DATA_PARAMETER_TAG:
1954     dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
1955     break;
1956   case TRAFFIC_MODE_TYPE_PARAMETER_TAG:
1957     dissect_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1958     break;
1959   case ERROR_CODE_PARAMETER_TAG:
1960     dissect_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
1961     break;
1962   case STATUS_PARAMETER_TAG:
1963     dissect_status_type_parameter(parameter_tvb, parameter_tree, parameter_item);
1964     break;
1965   case CONGESTION_LEVEL_PARAMETER_TAG:
1966     dissect_congestion_level_parameter(parameter_tvb, parameter_tree, parameter_item);
1967     break;
1968   case ASP_IDENTIFIER_PARAMETER_TAG:
1969     dissect_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1970     break;
1971   case AFFECTED_POINT_CODE_PARAMETER_TAG:
1972     dissect_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
1973     break;
1974   case REGISTRATION_STATUS_PARAMETER_TAG:
1975     dissect_registration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1976     break;
1977   case DEREGISTRATION_STATUS_PARAMETER_TAG:
1978     dissect_deregistration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
1979     break;
1980   case LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG:
1981     dissect_local_routing_key_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
1982     break;
1983   case SS7_HOP_COUNTER_PARAMETER_TAG:
1984     dissect_ss7_hop_counter_parameter(parameter_tvb, parameter_tree, parameter_item);
1985     break;
1986   case SOURCE_ADDRESS_PARAMETER_TAG:
1987     dissect_source_address_parameter(parameter_tvb, pinfo, parameter_tree, source_ssn);
1988     break;
1989   case DESTINATION_ADDRESS_PARAMETER_TAG:
1990     dissect_destination_address_parameter(parameter_tvb, pinfo, parameter_tree, dest_ssn);
1991     break;
1992   case SOURCE_REFERENCE_NUMBER_PARAMETER_TAG:
1993     dissect_source_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1994     break;
1995   case DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG:
1996     dissect_destination_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
1997     break;
1998   case SCCP_CAUSE_PARAMETER_TAG:
1999     dissect_sccp_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
2000     break;
2001   case SEQUENCE_NUMBER_PARAMETER_TAG:
2002     dissect_sequence_number_parameter(parameter_tvb, parameter_tree);
2003     break;
2004   case RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG:
2005     dissect_receive_sequence_number_parameter(parameter_tvb, parameter_tree);
2006     break;
2007   case ASP_CAPABILITIES_PARAMETER_TAG:
2008     dissect_asp_capabilities_parameter(parameter_tvb, parameter_tree);
2009     break;
2010   case CREDIT_PARAMETER_TAG:
2011     dissect_credit_parameter(parameter_tvb, parameter_tree, parameter_item);
2012     break;
2013   case USER_CAUSE_PARAMETER_TAG:
2014     dissect_user_cause_parameter(parameter_tvb, parameter_tree);
2015     break;
2016   case NETWORK_APPEARANCE_PARAMETER_TAG:
2017     dissect_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
2018     break;
2019   case ROUTING_KEY_PARAMETER_TAG:
2020     dissect_routing_key_parameter(parameter_tvb, pinfo, parameter_tree);
2021     break;
2022   case REGISTRATION_RESULT_PARAMETER_TAG:
2023     dissect_registration_result_parameter(parameter_tvb, pinfo, parameter_tree);
2024     break;
2025   case DEREGISTRATION_RESULT_PARAMETER_TAG:
2026     dissect_deregistration_result_parameter(parameter_tvb, pinfo, parameter_tree);
2027     break;
2028   case ADDRESS_RANGE_PARAMETER_TAG:
2029     dissect_address_range_parameter(parameter_tvb, pinfo, parameter_tree);
2030     break;
2031   case CORRELATION_ID_PARAMETER_TAG:
2032     dissect_correlation_id_parameter(parameter_tvb, parameter_tree, parameter_item);
2033     break;
2034   case IMPORTANCE_PARAMETER_TAG:
2035     dissect_importance_parameter(parameter_tvb, parameter_tree, parameter_item);
2036     break;
2037   case MESSAGE_PRIORITY_PARAMETER_TAG:
2038     dissect_message_priority_parameter(parameter_tvb, parameter_tree, parameter_item);
2039     break;
2040   case PROTOCOL_CLASS_PARAMETER_TAG:
2041     dissect_protocol_class_parameter(parameter_tvb, parameter_tree, parameter_item);
2042     break;
2043   case SEQUENCE_CONTROL_PARAMETER_TAG:
2044     dissect_sequence_control_parameter(parameter_tvb, parameter_tree, parameter_item);
2045     break;
2046   case SEGMENTATION_PARAMETER_TAG:
2047     dissect_segmentation_parameter(parameter_tvb, parameter_tree);
2048     break;
2049   case SMI_PARAMETER_TAG:
2050     dissect_smi_parameter(parameter_tvb, parameter_tree, parameter_item);
2051     break;
2052   case TID_LABEL_PARAMETER_TAG:
2053     dissect_tid_label_parameter(parameter_tvb, parameter_tree);
2054     break;
2055   case DRN_LABEL_PARAMETER_TAG:
2056     dissect_drn_label_parameter(parameter_tvb, parameter_tree);
2057     break;
2058   case GLOBAL_TITLE_PARAMETER_TAG:
2059     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
2060     dissect_global_title_parameter(parameter_tvb, parameter_tree, (source_ssn != NULL));
2061     break;
2062   case POINT_CODE_PARAMETER_TAG:
2063     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
2064     dissect_point_code_parameter(parameter_tvb, parameter_tree, parameter_item, (source_ssn != NULL));
2065     break;
2066   case SUBSYSTEM_NUMBER_PARAMETER_TAG:
2067     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
2068     dissect_ssn_parameter(parameter_tvb, parameter_tree, parameter_item, &ssn, (source_ssn != NULL));
2069     if(source_ssn)
2070     {
2071         *source_ssn = ssn;
2072     }
2073     if(dest_ssn)
2074     {
2075         *dest_ssn = ssn;
2076     }
2077     break;
2078   case IPV4_ADDRESS_PARAMETER_TAG:
2079     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
2080     dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item, (source_ssn != NULL));
2081     break;
2082   case HOSTNAME_PARAMETER_TAG:
2083     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
2084     dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item, (source_ssn != NULL));
2085     break;
2086   case IPV6_ADDRESS_PARAMETER_TAG:
2087     /* Reuse whether we have source_ssn or not to determine which address we're looking at */
2088     dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item, (source_ssn != NULL));
2089     break;
2090   default:
2091     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
2092     break;
2093   };
2094   if (parameter_tree && (padding_length > 0))
2095     proto_tree_add_item(parameter_tree, hf_sua_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, ENC_NA);
2096 }
2097 
2098 static void
dissect_parameters(tvbuff_t * parameters_tvb,packet_info * pinfo,proto_tree * tree,tvbuff_t ** data_tvb,guint8 * source_ssn,guint8 * dest_ssn)2099 dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn)
2100 {
2101   gint offset, length, total_length, remaining_length;
2102   tvbuff_t *parameter_tvb;
2103 
2104   offset = 0;
2105   while((remaining_length = tvb_reported_length_remaining(parameters_tvb, offset))) {
2106     length       = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
2107     total_length = ADD_PADDING(length);
2108     if (remaining_length >= length)
2109       total_length = MIN(total_length, remaining_length);
2110     /* create a tvb for the parameter including the padding bytes */
2111     parameter_tvb  = tvb_new_subset_length(parameters_tvb, offset, total_length);
2112     switch(version) {
2113       case SUA_V08:
2114         dissect_v8_parameter(parameter_tvb, pinfo, tree, data_tvb, source_ssn, dest_ssn);
2115         break;
2116       case SUA_RFC:
2117         dissect_parameter(parameter_tvb, pinfo, tree, data_tvb, source_ssn, dest_ssn);
2118         break;
2119     }
2120     /* get rid of the handled parameter */
2121     offset += total_length;
2122   }
2123 }
2124 
2125 static void
dissect_sua_message(tvbuff_t * message_tvb,packet_info * pinfo,proto_tree * sua_tree,proto_tree * tree)2126 dissect_sua_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *sua_tree, proto_tree *tree)
2127 {
2128   tvbuff_t *common_header_tvb;
2129   tvbuff_t *parameters_tvb;
2130   tvbuff_t *data_tvb = NULL;
2131 
2132   heur_dtbl_entry_t *hdtbl_entry;
2133 #if 0
2134   proto_tree *assoc_tree;
2135 #endif
2136   guint8 source_ssn = INVALID_SSN;
2137   guint8 dest_ssn = INVALID_SSN;
2138   proto_item *assoc_item;
2139   struct _sccp_msg_info_t* sccp_info = NULL;
2140 
2141   message_class = 0;
2142   message_type = 0;
2143   drn = 0;
2144   srn = 0;
2145 
2146   assoc = NULL;
2147   no_sua_assoc.calling_dpc = 0;
2148   no_sua_assoc.called_dpc = 0;
2149   no_sua_assoc.calling_ssn = INVALID_SSN;
2150   no_sua_assoc.called_ssn = INVALID_SSN;
2151   no_sua_assoc.has_bw_key = FALSE;
2152   no_sua_assoc.has_fw_key = FALSE;
2153 
2154   sua_opc = wmem_new0(pinfo->pool, mtp3_addr_pc_t);
2155   sua_dpc = wmem_new0(pinfo->pool, mtp3_addr_pc_t);
2156   sua_source_gt = NULL;
2157   sua_destination_gt = NULL;
2158 
2159   common_header_tvb = tvb_new_subset_length(message_tvb, COMMON_HEADER_OFFSET, COMMON_HEADER_LENGTH);
2160   dissect_common_header(common_header_tvb, pinfo, sua_tree);
2161 
2162   parameters_tvb = tvb_new_subset_remaining(message_tvb, COMMON_HEADER_LENGTH);
2163   dissect_parameters(parameters_tvb, pinfo, sua_tree, &data_tvb, &source_ssn, &dest_ssn);
2164 
2165 
2166 
2167   if (message_class == MESSAGE_CLASS_CO_MESSAGE) {
2168       /* XXX: this might fail with multihomed SCTP (on a path failure during a call)
2169        * or with "load sharing"?
2170        */
2171       sccp_assoc_info_t* sccp_assoc;
2172       sccp_decode_context_t sccp_decode;
2173       /* sua assoc */
2174 
2175       switch (message_type) {
2176               case MESSAGE_TYPE_CORE:
2177                       assoc = sua_assoc(pinfo,&(pinfo->src),&(pinfo->dst), srn , drn);
2178                       if(assoc) {
2179                               assoc->calling_routing_ind = sua_ri;
2180                               assoc->calling_ssn = source_ssn;
2181                               assoc->called_ssn = dest_ssn;
2182                       }
2183                       break;
2184               case MESSAGE_TYPE_COAK:
2185                       assoc = sua_assoc(pinfo,&(pinfo->src),&(pinfo->dst), srn , drn);
2186                       if(assoc) {
2187                               assoc->called_routing_ind = sua_ri;
2188                               if( (assoc->called_ssn != INVALID_SSN)&& (dest_ssn != INVALID_SSN)) {
2189                                       assoc->called_ssn = dest_ssn;
2190                               }
2191                       }
2192                       break;
2193               default :
2194                       assoc = sua_assoc(pinfo,&(pinfo->src),&(pinfo->dst), srn , drn);
2195       }
2196 
2197       switch (message_type) {
2198               case MESSAGE_TYPE_CORE:
2199               case MESSAGE_TYPE_COAK:
2200                        break;
2201               default:
2202                       if((assoc && assoc->called_ssn != INVALID_SSN)&& (dest_ssn != INVALID_SSN)) {
2203                               dest_ssn = assoc->called_ssn;
2204                       }
2205                       if((assoc && assoc->calling_ssn != INVALID_SSN)&& (source_ssn != INVALID_SSN)) {
2206                               source_ssn = assoc->calling_ssn;
2207                       }
2208 
2209       }
2210       if (assoc && assoc->assoc_id !=0) {
2211           assoc_item = proto_tree_add_uint(tree, hf_sua_assoc_id, message_tvb, 0, 0, assoc->assoc_id);
2212           proto_item_set_generated(assoc_item);
2213 #if 0
2214           assoc_tree = proto_item_add_subtree(assoc_item, ett_sua_assoc);
2215           proto_tree_add_debug_text(assoc_tree, message_tvb, 0, 0, "routing_ind %u", assoc->calling_routing_ind);
2216           proto_tree_add_debug_text(assoc_tree, message_tvb, 0, 0, "routing_ind %u", assoc->called_routing_ind);
2217           proto_tree_add_debug_text(assoc_tree, message_tvb, 0, 0, "calling_ssn %u", assoc->calling_ssn);
2218           proto_tree_add_debug_text(assoc_tree, message_tvb, 0, 0, "called_ssn %u", assoc->called_ssn);
2219 #endif /* 0 */
2220       }
2221 
2222       sccp_decode.message_type = message_type;
2223       sccp_decode.dlr = drn;
2224       sccp_decode.slr = srn;
2225       sccp_decode.assoc = NULL;
2226       sccp_decode.sccp_msg = NULL; /* Unused, but initialized */
2227 
2228       sccp_assoc = get_sccp_assoc(pinfo, tvb_offset_from_real_beginning(message_tvb), &sccp_decode);
2229       if (sccp_assoc && sccp_assoc->curr_msg) {
2230               sccp_info = sccp_assoc->curr_msg;
2231               tap_queue_packet(sua_tap,pinfo,sccp_assoc->curr_msg);
2232       }
2233   }
2234 
2235   if (set_addresses) {
2236     if (sua_opc->type)
2237       set_address(&pinfo->src, ss7pc_address_type, sizeof(mtp3_addr_pc_t), (guint8 *) sua_opc);
2238     if (sua_dpc->type)
2239       set_address(&pinfo->dst, ss7pc_address_type, sizeof(mtp3_addr_pc_t), (guint8 *) sua_dpc);
2240 
2241     if (sua_source_gt)
2242       set_address(&pinfo->src, AT_STRINGZ, 1+(int)strlen(sua_source_gt), wmem_strdup(pinfo->pool, sua_source_gt));
2243     if (sua_destination_gt)
2244       set_address(&pinfo->dst, AT_STRINGZ, 1+(int)strlen(sua_destination_gt), wmem_strdup(pinfo->pool, sua_destination_gt));
2245   }
2246 
2247   /* If there was SUA data it could be dissected */
2248   if(data_tvb)
2249   {
2250     /* Try subdissectors (if we found a valid SSN on the current message) */
2251     if ((dest_ssn == INVALID_SSN ||
2252        !dissector_try_uint_new(sccp_ssn_dissector_table, dest_ssn, data_tvb, pinfo, tree, TRUE, sccp_info))
2253        && (source_ssn == INVALID_SSN ||
2254        !dissector_try_uint_new(sccp_ssn_dissector_table, source_ssn, data_tvb, pinfo, tree, TRUE, sccp_info)))
2255     {
2256       /* try heuristic subdissector list to see if there are any takers */
2257       if (dissector_try_heuristic(heur_subdissector_list, data_tvb, pinfo, tree, &hdtbl_entry, sccp_info)) {
2258         return;
2259       }
2260       /* No sub-dissection occurred, treat it as raw data */
2261       call_data_dissector(data_tvb, pinfo, tree);
2262     }
2263   }
2264 }
2265 
2266 static int
dissect_sua(tvbuff_t * message_tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2267 dissect_sua(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2268 {
2269   proto_item *sua_item;
2270   proto_tree *sua_tree;
2271 
2272   /* make entry in the Protocol column on summary display */
2273 
2274   switch (version) {
2275     case SUA_V08:
2276       col_set_str(pinfo->cinfo, COL_PROTOCOL, "SUA (ID 08)");
2277       break;
2278     case SUA_RFC:
2279       col_set_str(pinfo->cinfo, COL_PROTOCOL, "SUA (RFC 3868)");
2280       break;
2281   }
2282 
2283   /* Clear entries in Info column on summary display */
2284   col_clear(pinfo->cinfo, COL_INFO);
2285 
2286   /* create the sua protocol tree */
2287   sua_item = proto_tree_add_item(tree, proto_sua, message_tvb, 0, -1, ENC_NA);
2288   sua_tree = proto_item_add_subtree(sua_item, ett_sua);
2289 
2290   /* dissect the message */
2291   dissect_sua_message(message_tvb, pinfo, sua_tree, tree);
2292   return tvb_captured_length(message_tvb);
2293 }
2294 
2295 /* Register the protocol with Wireshark */
2296 void
proto_register_sua(void)2297 proto_register_sua(void)
2298 {
2299 
2300   /* Setup list of header fields */
2301   static hf_register_info hf[] = {
2302     { &hf_sua_version,                               { "Version",                      "sua.version",                                   FT_UINT8,   BASE_DEC,  VALS(protocol_version_values),      0x0,                      NULL, HFILL } },
2303     { &hf_sua_reserved,                              { "Reserved",                     "sua.reserved",                                  FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2304     { &hf_sua_message_class,                         { "Message Class",                "sua.message_class",                             FT_UINT8,   BASE_DEC,  VALS(message_class_values),         0x0,                      NULL, HFILL } },
2305     { &hf_sua_message_type,                          { "Message Type",                 "sua.message_type",                              FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2306     { &hf_sua_message_length,                        { "Message Length",               "sua.message_length",                            FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2307     { &hf_sua_parameter_tag,                         { "Parameter Tag",                "sua.parameter_tag",                             FT_UINT16,  BASE_HEX,  VALS(parameter_tag_values),         0x0,                      NULL, HFILL } },
2308     { &hf_sua_v8_parameter_tag,                      { "Parameter Tag",                "sua.parameter_tag",                             FT_UINT16,  BASE_HEX,  VALS(v8_parameter_tag_values),      0x0,                      NULL, HFILL } },
2309     { &hf_sua_parameter_length,                      { "Parameter Length",             "sua.parameter_length",                          FT_UINT16,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2310     { &hf_sua_parameter_value,                       { "Parameter Value",              "sua.parameter_value",                           FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2311     { &hf_sua_parameter_padding,                     { "Padding",                      "sua.parameter_padding",                         FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2312     { &hf_sua_info_string,                           { "Info string",                  "sua.info_string",                               FT_STRING,  BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2313     { &hf_sua_routing_context,                       { "Routing context",              "sua.routing_context",                           FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2314     { &hf_sua_diagnostic_information_info,           { "Diagnostic Information",       "sua.diagnostic_information",                    FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2315     { &hf_sua_heartbeat_data,                        { "Heartbeat Data",               "sua.heartbeat_data",                            FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2316     { &hf_sua_traffic_mode_type,                     { "Traffic mode Type",            "sua.traffic_mode_type",                         FT_UINT32,  BASE_DEC,  VALS(traffic_mode_type_values),     0x0,                      NULL, HFILL } },
2317     { &hf_sua_error_code,                            { "Error code",                   "sua.error_code",                                FT_UINT32,  BASE_DEC,  VALS(error_code_values),            0x0,                      NULL, HFILL } },
2318     { &hf_sua_v8_error_code,                         { "Error code",                   "sua.error_code",                                FT_UINT32,  BASE_DEC,  VALS(v8_error_code_values),         0x0,                      NULL, HFILL } },
2319     { &hf_sua_status_type,                           { "Status type",                  "sua.status_type",                               FT_UINT16,  BASE_DEC,  VALS(status_type_values),           0x0,                      NULL, HFILL } },
2320     { &hf_sua_status_info,                           { "Status info",                  "sua.status_info",                               FT_UINT16,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2321     { &hf_sua_congestion_level,                      { "Congestion Level",             "sua.congestion_level",                          FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2322     { &hf_sua_asp_identifier,                        { "ASP Identifier",               "sua.asp_identifier",                            FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2323     { &hf_sua_mask,                                  { "Mask",                         "sua.affected_point_code_mask",                  FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2324     { &hf_sua_dpc,                                   { "Affected DPC",                 "sua.affected_pointcode_dpc",                    FT_UINT24,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2325     { &hf_sua_registration_status,                   { "Registration status",          "sua.registration_status",                       FT_UINT32,  BASE_DEC,  VALS(registration_status_values),   0x0,                      NULL, HFILL } },
2326     { &hf_sua_deregistration_status,                 { "Deregistration status",        "sua.deregistration_status",                     FT_UINT32,  BASE_DEC,  VALS(deregistration_status_values), 0x0,                      NULL, HFILL } },
2327     { &hf_sua_local_routing_key_identifier,          { "Local routing key identifier", "sua.local_routing_key_identifier",              FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2328 
2329     { &hf_sua_source_address_routing_indicator,      { "Source Routing Indicator",     "sua.source.routing_indicator",                  FT_UINT16,  BASE_DEC,  VALS(routing_indicator_values),     0x0,                      NULL, HFILL } },
2330     { &hf_sua_source_address_reserved_bits,          { "Source Reserved Bits",         "sua.source.reserved_bits",                      FT_UINT16,  BASE_DEC,  NULL,                               ADDRESS_RESERVED_BITMASK, NULL, HFILL } },
2331     { &hf_sua_source_address_gt_bit,                 { "Source Include GT",            "sua.source.gt_bit",                             FT_BOOLEAN, 16,        NULL,                               ADDRESS_GT_BITMASK,       NULL, HFILL } },
2332     { &hf_sua_source_address_pc_bit,                 { "Source Include PC",            "sua.source.pc_bit",                             FT_BOOLEAN, 16,        NULL,                               ADDRESS_PC_BITMASK,       NULL, HFILL } },
2333     { &hf_sua_source_address_ssn_bit,                { "Source Include SSN",           "sua.source.ssn_bit",                            FT_BOOLEAN, 16,        NULL,                               ADDRESS_SSN_BITMASK,      NULL, HFILL } },
2334     { &hf_sua_source_gt_reserved,                    { "Source Reserved",              "sua.source.gt_reserved",                        FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2335     { &hf_sua_source_gti,                            { "Source GTI",                   "sua.source.gti",                                FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2336     { &hf_sua_source_number_of_digits,               { "Source Number of Digits",      "sua.source.global_title_number_of_digits",      FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2337     { &hf_sua_source_translation_type,               { "Source Translation Type",      "sua.source.global_title_translation_type",      FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2338     { &hf_sua_source_numbering_plan,                 { "Source Numbering Plan",        "sua.source.global_title_numbering_plan",        FT_UINT8,   BASE_HEX,  VALS(numbering_plan_values),        0x0,                      NULL, HFILL } },
2339     { &hf_sua_source_nature_of_address,              { "Source Nature of Address",     "sua.source.global_title_nature_of_address",     FT_UINT8,   BASE_HEX,  VALS(nature_of_address_values),     0x0,                      NULL, HFILL } },
2340     { &hf_sua_source_global_title_digits,            { "Source Global Title Digits",   "sua.source.global_title_digits",                FT_STRING,  BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2341     { &hf_sua_source_point_code,                     { "Source Point Code",            "sua.source.point_code",                         FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2342     { &hf_sua_source_ssn_reserved,                   { "Source Reserved",              "sua.source.ssn_reserved",                       FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2343     { &hf_sua_source_ssn_number,                     { "Source Subsystem Number",      "sua.source.ssn",                                FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2344     { &hf_sua_source_ipv4,                           { "Source IP Version 4 address",  "sua.source.ipv4_address",                       FT_IPv4,    BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2345     { &hf_sua_source_hostname,                       { "Source Hostname",              "sua.source.hostname.name",                      FT_STRING,  BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2346     { &hf_sua_source_ipv6,                           { "Source IP Version 6 address",  "sua.source.ipv6_address",                       FT_IPv6,    BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2347 
2348     { &hf_sua_destination_address_routing_indicator, { "Destination Routing Indicator","sua.destination.routing_indicator",             FT_UINT16,  BASE_DEC,  VALS(routing_indicator_values),     0x0,                      NULL, HFILL } },
2349     { &hf_sua_destination_address_reserved_bits,     { "Destination Reserved Bits",    "sua.destination.reserved_bits",                 FT_UINT16,  BASE_DEC,  NULL,                               ADDRESS_RESERVED_BITMASK, NULL, HFILL } },
2350     { &hf_sua_destination_address_gt_bit,            { "Destination Include GT",       "sua.destination.gt_bit",                        FT_BOOLEAN, 16,        NULL,                               ADDRESS_GT_BITMASK,       NULL, HFILL } },
2351     { &hf_sua_destination_address_pc_bit,            { "Destination Include PC",       "sua.destination.pc_bit",                        FT_BOOLEAN, 16,        NULL,                               ADDRESS_PC_BITMASK,       NULL, HFILL } },
2352     { &hf_sua_destination_address_ssn_bit,           { "Destination Include SSN",      "sua.destination.ssn_bit",                       FT_BOOLEAN, 16,        NULL,                               ADDRESS_SSN_BITMASK,      NULL, HFILL } },
2353     { &hf_sua_dest_gt_reserved,                      { "Destination Reserved",         "sua.destination.gt_reserved",                   FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2354     { &hf_sua_dest_gti,                              { "Destination GTI",              "sua.destination.gti",                           FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2355     { &hf_sua_dest_number_of_digits,                 { "Destination Number of Digits", "sua.destination.global_title_number_of_digits", FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2356     { &hf_sua_dest_translation_type,                 { "Destination Translation Type", "sua.destination.global_title_translation_type", FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2357     { &hf_sua_dest_numbering_plan,                   { "Destination Numbering Plan",   "sua.destination.global_title_numbering_plan",   FT_UINT8,   BASE_HEX,  VALS(numbering_plan_values),        0x0,                      NULL, HFILL } },
2358     { &hf_sua_dest_nature_of_address,                { "Destination Nature of Address","sua.destination.global_title_nature_of_address",FT_UINT8,   BASE_HEX,  VALS(nature_of_address_values),     0x0,                      NULL, HFILL } },
2359     { &hf_sua_dest_global_title_digits,              { "Destination Global Title Digits","sua.destination.global_title_digits",         FT_STRING,  BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2360     { &hf_sua_dest_point_code,                       { "Destination Point Code",       "sua.destination.point_code",                    FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2361     { &hf_sua_dest_ssn_reserved,                     { "Destination Reserved",         "sua.destination.ssn_reserved",                  FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2362     { &hf_sua_dest_ssn_number,                       { "Destination Subsystem Number", "sua.destination.ssn",                           FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2363     { &hf_sua_dest_ipv4,                             { "Destination IPv4 address",     "sua.destination.ipv4_address",                  FT_IPv4,    BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2364     { &hf_sua_dest_hostname,                         { "Destination Hostname",         "sua.destination.hostname.name",                 FT_STRING,  BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2365     { &hf_sua_dest_ipv6,                             { "Destination IPv6 address",     "sua.destination.ipv6_address",                  FT_IPv6,    BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2366 
2367     { &hf_sua_ss7_hop_counter_counter,               { "SS7 Hop Counter",              "sua.ss7_hop_counter_counter",                   FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2368     { &hf_sua_ss7_hop_counter_reserved,              { "Reserved",                     "sua.ss7_hop_counter_reserved",                  FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2369     { &hf_sua_destination_reference_number,          { "Destination Reference Number", "sua.destination_reference_number",              FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2370     { &hf_sua_source_reference_number,               { "Source Reference Number",      "sua.source_reference_number",                   FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2371     { &hf_sua_cause_reserved,                        { "Reserved",                     "sua.sccp_cause_reserved",                       FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2372     { &hf_sua_cause_type,                            { "Cause Type",                   "sua.sccp_cause_type",                           FT_UINT8,   BASE_HEX,  VALS(cause_type_values),            0x0,                      NULL, HFILL } },
2373     { &hf_sua_cause_value,                           { "Cause Value",                  "sua.sccp_cause_value",                          FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2374     { &hf_sua_sequence_number_reserved,              { "Reserved",                     "sua.sequence_number_reserved",                  FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2375     { &hf_sua_sequence_number_rec_number,            { "Receive Sequence Number P(R)", "sua.sequence_number_receive_sequence_number",   FT_UINT8,   BASE_DEC,  NULL,                               SEQ_NUM_MASK,             NULL, HFILL } },
2376     { &hf_sua_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,       NULL, HFILL } },
2377     { &hf_sua_sequence_number_sent_number,           { "Sent Sequence Number P(S)",    "sua.sequence_number_sent_sequence_number",      FT_UINT8,   BASE_DEC,  NULL,                               SEQ_NUM_MASK,             NULL, HFILL } },
2378     { &hf_sua_sequence_number_spare_bit,             { "Spare Bit",                    "sua.sequence_number_spare_bit",                 FT_UINT8,   BASE_DEC,  NULL,                               SPARE_BIT_MASK,           NULL, HFILL } },
2379     { &hf_sua_receive_sequence_number_reserved,      { "Reserved",                     "sua.receive_sequence_number_reserved",          FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2380     { &hf_sua_receive_sequence_number_number,        { "Receive Sequence Number P(R)", "sua.receive_sequence_number_number",            FT_UINT8,   BASE_DEC,  NULL,                               SEQ_NUM_MASK,             NULL, HFILL } },
2381     { &hf_sua_receive_sequence_number_spare_bit,     { "Spare Bit",                    "sua.receive_sequence_number_spare_bit",         FT_UINT8,   BASE_DEC,  NULL,                               SPARE_BIT_MASK,           NULL, HFILL } },
2382     { &hf_sua_asp_capabilities_reserved,             { "Reserved",                     "sua.asp_capabilities_reserved",                 FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2383     { &hf_sua_protocol_classes,                      { "Protocol classes",             "sua.protocol_classes",                          FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2384     { &hf_sua_protocol_class_flags,                  { "Protocol class",               "sua.protocol_class_flags",                      FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2385     { &hf_sua_asp_capabilities_reserved_bits,        { "Reserved Bits",                "sua.asp_capabilities_reserved_bits",            FT_UINT8,   BASE_HEX,  NULL,                               RESERVED_BITS_MASK,       NULL, HFILL } },
2386     { &hf_sua_asp_capabilities_a_bit,                { "Protocol Class 3",             "sua.asp_capabilities_a_bit",                    FT_BOOLEAN, 8,         TFS(&tfs_supported_not_supported),  A_BIT_MASK,               NULL, HFILL } },
2387     { &hf_sua_asp_capabilities_b_bit,                { "Protocol Class 2",             "sua.asp_capabilities_b_bit",                    FT_BOOLEAN, 8,         TFS(&tfs_supported_not_supported),  B_BIT_MASK,               NULL, HFILL } },
2388     { &hf_sua_asp_capabilities_c_bit,                { "Protocol Class 1",             "sua.asp_capabilities_c_bit",                    FT_BOOLEAN, 8,         TFS(&tfs_supported_not_supported),  C_BIT_MASK,               NULL, HFILL } },
2389     { &hf_sua_asp_capabilities_d_bit,                { "Protocol Class 0",             "sua.asp_capabilities_d_bit",                    FT_BOOLEAN, 8,         TFS(&tfs_supported_not_supported),  D_BIT_MASK,               NULL, HFILL } },
2390     { &hf_sua_asp_capabilities_interworking,         { "Interworking",                 "sua.asp_capabilities_interworking",             FT_UINT8,   BASE_HEX,  VALS(interworking_values),          0x0,                      NULL, HFILL } },
2391     { &hf_sua_credit,                                { "Credit",                       "sua.credit",                                    FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2392     { &hf_sua_cause,                                 { "Cause",                        "sua.cause_user_cause",                          FT_UINT16,  BASE_DEC,  VALS(cause_values),                 0x0,                      NULL, HFILL } },
2393     { &hf_sua_user,                                  { "User",                         "sua.cause_user_user",                           FT_UINT16,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2394     { &hf_sua_data,                                  { "Data",                         "sua.data",                                      FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2395     { &hf_sua_network_appearance,                    { "Network Appearance",           "sua.network_appearance",                        FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2396     { &hf_sua_correlation_id,                        { "Correlation ID",               "sua.correlation_id",                            FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2397     { &hf_sua_importance_reserved,                   { "Reserved",                     "sua.importance_reserved",                       FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2398     { &hf_sua_importance,                            { "Importance",                   "sua.importance_importance",                     FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2399     { &hf_sua_message_priority_reserved,             { "Reserved",                     "sua.message_priority_reserved",                 FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2400     { &hf_sua_message_priority,                      { "Message Priority",             "sua.message_priority_priority",                 FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2401     { &hf_sua_protocol_class_reserved,               { "Reserved",                     "sua.protocol_class_reserved",                    FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2402     { &hf_sua_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, NULL, HFILL } },
2403     { &hf_sua_protocol_class,                        { "Protocol Class",               "sua.protocol_class_class",                      FT_UINT8,   BASE_DEC,  NULL,                               PROTOCOL_CLASS_MASK,      NULL, HFILL } },
2404     { &hf_sua_sequence_control,                      { "Sequence Control",             "sua.sequence_control_sequence_control",         FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2405     { &hf_sua_first_remaining,                       { "First / Remaining",            "sua.first_remaining",                           FT_UINT8,   BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2406     { &hf_sua_first_bit,                             { "First Segment Bit",            "sua.segmentation_first_bit",                    FT_BOOLEAN, 8,         TFS(&first_bit_value),              FIRST_BIT_MASK,           NULL, HFILL } },
2407     { &hf_sua_number_of_remaining_segments,          { "Number of Remaining Segments", "sua.segmentation_number_of_remaining_segments", FT_UINT8,   BASE_DEC,  NULL,                               NUMBER_OF_SEGMENTS_MASK,  NULL, HFILL } },
2408     { &hf_sua_segmentation_reference,                { "Segmentation Reference",       "sua.segmentation_reference",                    FT_UINT24,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2409     { &hf_sua_smi_reserved,                          { "Reserved",                     "sua.smi_reserved",                              FT_BYTES,   BASE_NONE, NULL,                               0x0,                      NULL, HFILL } },
2410     { &hf_sua_smi,                                   { "SMI",                          "sua.smi_smi",                                   FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2411     { &hf_sua_tid_label_start,                       { "Start",                        "sua.tid_label_start",                           FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2412     { &hf_sua_tid_label_end,                         { "End",                          "sua.tid_label_end",                             FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2413     { &hf_sua_tid_label_value,                       { "Label Value",                  "sua.tid_label_value",                           FT_UINT16,  BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2414     { &hf_sua_drn_label_start,                       { "Start",                        "sua.drn_label_start",                           FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2415     { &hf_sua_drn_label_end,                         { "End",                          "sua.drn_label_end",                             FT_UINT8,   BASE_DEC,  NULL,                               0x0,                      NULL, HFILL } },
2416     { &hf_sua_drn_label_value,                       { "Label Value",                  "sua.drn_label_value",                           FT_UINT16,  BASE_HEX,  NULL,                               0x0,                      NULL, HFILL } },
2417 
2418     { &hf_sua_assoc_id,                              { "Association ID",               "sua.assoc.id",                                  FT_UINT32,  BASE_DEC,  NULL,                               0x0,                      NULL, HFILL}},
2419  };
2420 
2421   /* Setup protocol subtree array */
2422   static gint *ett[] = {
2423     &ett_sua,
2424     &ett_sua_parameter,
2425     &ett_sua_source_address_indicator,
2426     &ett_sua_destination_address_indicator,
2427     &ett_sua_affected_destination,
2428     &ett_sua_sequence_number_rec_number,
2429     &ett_sua_sequence_number_sent_number,
2430     &ett_sua_receive_sequence_number_number,
2431     &ett_sua_protocol_classes,
2432     &ett_sua_first_remaining,
2433     &ett_sua_return_on_error_bit_and_protocol_class,
2434     &ett_sua_assoc
2435 
2436   };
2437 
2438   module_t *sua_module;
2439 
2440   static const enum_val_t options[] = {
2441     { "draft-08", "Internet Draft version 08", SUA_V08  },
2442     { "rfc3868",  "RFC 3868",                  SUA_RFC  },
2443     { NULL, NULL, 0 }
2444   };
2445 
2446   /* Register the protocol name and description */
2447   proto_sua = proto_register_protocol("SS7 SCCP-User Adaptation Layer", "SUA", "sua");
2448   sua_handle = register_dissector("sua", dissect_sua, proto_sua);
2449 
2450   /* Required function calls to register the header fields and subtrees used */
2451   proto_register_field_array(proto_sua, hf, array_length(hf));
2452   proto_register_subtree_array(ett, array_length(ett));
2453 
2454   sua_module = prefs_register_protocol(proto_sua, NULL);
2455   prefs_register_obsolete_preference(sua_module, "sua_version");
2456   prefs_register_enum_preference(sua_module, "version", "SUA Version", "Version used by Wireshark", &version, options, FALSE);
2457   prefs_register_bool_preference(sua_module, "set_addresses", "Set source and destination addresses",
2458                                  "Set the source and destination addresses to the PC or GT digits, depending on the routing indicator."
2459                                  "  This may affect TCAP's ability to recognize which messages belong to which TCAP session.", &set_addresses);
2460 
2461   heur_subdissector_list = register_heur_dissector_list("sua", proto_sua);
2462   sua_parameter_table = register_dissector_table("sua.prop.tags", "SUA Proprietary Tags", proto_sua, FT_UINT16, BASE_DEC);
2463   sua_tap = register_tap("sua");
2464 
2465   assocs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
2466 }
2467 
2468 void
proto_reg_handoff_sua(void)2469 proto_reg_handoff_sua(void)
2470 {
2471   /* Do we have an info string dissector ? */
2472   sua_info_str_handle = find_dissector("sua.infostring");
2473   dissector_add_uint("sctp.ppi",  SUA_PAYLOAD_PROTOCOL_ID, sua_handle);
2474   dissector_add_uint("sctp.port", SCTP_PORT_SUA,           sua_handle);
2475 
2476   sccp_ssn_dissector_table = find_dissector_table("sccp.ssn");
2477 
2478   ss7pc_address_type = address_type_get_by_name("AT_SS7PC");
2479 }
2480 
2481 /*
2482  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2483  *
2484  * Local Variables:
2485  * c-basic-offset: 2
2486  * tab-width: 8
2487  * indent-tabs-mode: nil
2488  * End:
2489  *
2490  * ex: set shiftwidth=2 tabstop=8 expandtab:
2491  * :indentSize=2:tabSize=8:noTabs=true:
2492  */
2493