Mine:
[obnox/wireshark/wip.git] / epan / dissectors / packet-sccp.c
1 /* packet-sccp.c
2  * Routines for Signalling Connection Control Part (SCCP) dissection
3  *
4  * It is hopefully compliant to:
5  *   ANSI T1.112.3-1996
6  *   ITU-T Q.713 7/1996
7  *   YDN 038-1997 (Chinese ITU variant)
8  *   JT-Q713 and NTT-Q713 (Japan)
9  *
10  *   Note that Japan-specific GTT is incomplete; in particular, the specific
11  *   TTs that are defined in TTC and NTT are not decoded in detail.
12  *
13  * Copyright 2002, Jeff Morriss <jeff.morriss[AT]ulticom.com>
14  *
15  * $Id$
16  *
17  * Wireshark - Network traffic analyzer
18  * By Gerald Combs <gerald@wireshark.org>
19  * Copyright 1998 Gerald Combs
20  *
21  * Copied from packet-m2pa.c
22  *
23  * This program is free software; you can redistribute it and/or
24  * modify it under the terms of the GNU General Public License
25  * as published by the Free Software Foundation; either version 2
26  * of the License, or (at your option) any later version.
27  *
28  * This program is distributed in the hope that it will be useful,
29  * but WITHOUT ANY WARRANTY; without even the implied warranty of
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31  * GNU General Public License for more details.
32  *
33  * You should have received a copy of the GNU General Public License
34  * along with this program; if not, write to the Free Software
35  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36  */
37
38 #ifdef HAVE_CONFIG_H
39 # include "config.h"
40 #endif
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45
46 #include <glib.h>
47
48 #include <epan/packet.h>
49 #include "packet-mtp3.h"
50 #include <epan/prefs.h>
51 #include <epan/emem.h>
52 #include <epan/reassemble.h>
53 #include "packet-tcap.h"
54 #include "packet-sccp.h"
55 #include "tap.h"
56
57 static Standard_Type decode_mtp3_standard;
58 #define SCCP_SI 3
59
60 #define SCCP_MSG_TYPE_OFFSET 0
61 #define SCCP_MSG_TYPE_LENGTH 1
62 #define POINTER_LENGTH      1
63 #define POINTER_LENGTH_LONG 2
64
65 /* Same as below but with names typed out */
66 static const value_string sccp_message_type_values[] = {
67   { SCCP_MSG_TYPE_CR,     "Connection Request" },
68   { SCCP_MSG_TYPE_CC,     "Connection Confirm" },
69   { SCCP_MSG_TYPE_CREF,   "Connection Refused" },
70   { SCCP_MSG_TYPE_RLSD,   "Released" },
71   { SCCP_MSG_TYPE_RLC,    "Release Complete" },
72   { SCCP_MSG_TYPE_DT1,    "Data Form 1" },
73   { SCCP_MSG_TYPE_DT2,    "Data Form 2" },
74   { SCCP_MSG_TYPE_AK,     "Data Acknowledgement" },
75   { SCCP_MSG_TYPE_UDT,    "Unitdata" },
76   { SCCP_MSG_TYPE_UDTS,   "Unitdata Service" },
77   { SCCP_MSG_TYPE_ED,     "Expedited Data" },
78   { SCCP_MSG_TYPE_EA,     "Expedited Data Acknowledgement" },
79   { SCCP_MSG_TYPE_RSR,    "Reset Request" },
80   { SCCP_MSG_TYPE_RSC,    "Reset Confirmation" },
81   { SCCP_MSG_TYPE_ERR,    "Error" },
82   { SCCP_MSG_TYPE_IT,     "Inactivity Timer" },
83   { SCCP_MSG_TYPE_XUDT,   "Extended Unitdata" },
84   { SCCP_MSG_TYPE_XUDTS,  "Extended Unitdata Service" },
85   { SCCP_MSG_TYPE_LUDT,   "Long Unitdata (ITU)" },
86   { SCCP_MSG_TYPE_LUDTS,  "Long Unitdata Service (ITU)" },
87   { 0,                   NULL } };
88
89 /* Same as above but in acronym form (for the Info column) */
90 const value_string sccp_message_type_acro_values[] = {
91   { SCCP_MSG_TYPE_CR,     "CR" },
92   { SCCP_MSG_TYPE_CC,     "CC" },
93   { SCCP_MSG_TYPE_CREF,   "CREF" },
94   { SCCP_MSG_TYPE_RLSD,   "RLSD" },
95   { SCCP_MSG_TYPE_RLC,    "RLC" },
96   { SCCP_MSG_TYPE_DT1,    "DT1" },
97   { SCCP_MSG_TYPE_DT2,    "DT2" },
98   { SCCP_MSG_TYPE_AK,     "AK" },
99   { SCCP_MSG_TYPE_UDT,    "UDT" },
100   { SCCP_MSG_TYPE_UDTS,   "UDTS" },
101   { SCCP_MSG_TYPE_ED,     "ED" },
102   { SCCP_MSG_TYPE_EA,     "EA" },
103   { SCCP_MSG_TYPE_RSR,    "RSR" },
104   { SCCP_MSG_TYPE_RSC,    "RSC" },
105   { SCCP_MSG_TYPE_ERR,    "ERR" },
106   { SCCP_MSG_TYPE_IT,     "IT" },
107   { SCCP_MSG_TYPE_XUDT,   "XUDT" },
108   { SCCP_MSG_TYPE_XUDTS,  "XUDTS" },
109   { SCCP_MSG_TYPE_LUDT,   "LUDT" },
110   { SCCP_MSG_TYPE_LUDTS,  "LUDTS" },
111   { 0,                   NULL } };
112
113 #define PARAMETER_LENGTH_LENGTH 1
114 #define PARAMETER_LONG_DATA_LENGTH_LENGTH 2
115 #define PARAMETER_TYPE_LENGTH 1
116
117 #define PARAMETER_END_OF_OPTIONAL_PARAMETERS    0x00
118 #define PARAMETER_DESTINATION_LOCAL_REFERENCE   0x01
119 #define PARAMETER_SOURCE_LOCAL_REFERENCE        0x02
120 #define PARAMETER_CALLED_PARTY_ADDRESS          0x03
121 #define PARAMETER_CALLING_PARTY_ADDRESS         0x04
122 #define PARAMETER_CLASS                         0x05
123 #define PARAMETER_SEGMENTING_REASSEMBLING       0x06
124 #define PARAMETER_RECEIVE_SEQUENCE_NUMBER       0x07
125 #define PARAMETER_SEQUENCING_SEGMENTING         0x08
126 #define PARAMETER_CREDIT                        0x09
127 #define PARAMETER_RELEASE_CAUSE                 0x0a
128 #define PARAMETER_RETURN_CAUSE                  0x0b
129 #define PARAMETER_RESET_CAUSE                   0x0c
130 #define PARAMETER_ERROR_CAUSE                   0x0d
131 #define PARAMETER_REFUSAL_CAUSE                 0x0e
132 #define PARAMETER_DATA                          0x0f
133 #define PARAMETER_SEGMENTATION                  0x10
134 #define PARAMETER_HOP_COUNTER                   0x11
135 /* The below 2 are ITU only */
136 #define PARAMETER_IMPORTANCE                    0x12
137 #define PARAMETER_LONG_DATA                     0x13
138 /* ISNI is ANSI only */
139 #define PARAMETER_ISNI                          0xfa
140
141 static const value_string sccp_parameter_values[] = {
142   { PARAMETER_END_OF_OPTIONAL_PARAMETERS, "End of Optional Parameters" },
143   { PARAMETER_DESTINATION_LOCAL_REFERENCE, "Destination Local Reference" },
144   { PARAMETER_SOURCE_LOCAL_REFERENCE,     "Source Local Reference" },
145   { PARAMETER_CALLED_PARTY_ADDRESS,       "Called Party Address" },
146   { PARAMETER_CALLING_PARTY_ADDRESS,      "Calling Party Address" },
147   { PARAMETER_CLASS,                      "Protocol Class" },
148   { PARAMETER_SEGMENTING_REASSEMBLING,    "Segmenting/Reassembling" },
149   { PARAMETER_RECEIVE_SEQUENCE_NUMBER,    "Receive Sequence Number" },
150   { PARAMETER_SEQUENCING_SEGMENTING,      "Sequencing/Segmenting" },
151   { PARAMETER_CREDIT,                     "Credit" },
152   { PARAMETER_RELEASE_CAUSE,              "Release Cause" },
153   { PARAMETER_RETURN_CAUSE,               "Return Cause" },
154   { PARAMETER_RESET_CAUSE,                "Reset Cause" },
155   { PARAMETER_ERROR_CAUSE,                "Error Cause" },
156   { PARAMETER_REFUSAL_CAUSE,              "Refusal Cause" },
157   { PARAMETER_DATA,                       "Data" },
158   { PARAMETER_SEGMENTATION,               "Segmentation" },
159   { PARAMETER_HOP_COUNTER,                "Hop Counter" },
160   { PARAMETER_IMPORTANCE,                 "Importance (ITU)" },
161   { PARAMETER_LONG_DATA,                  "Long Data (ITU)" },
162   { PARAMETER_ISNI,                       "Intermediate Signaling Network Identification (ANSI)" },
163   { 0,                                    NULL } };
164
165
166 #define END_OF_OPTIONAL_PARAMETERS_LENGTH       1
167 #define DESTINATION_LOCAL_REFERENCE_LENGTH      3
168 #define SOURCE_LOCAL_REFERENCE_LENGTH           3
169 #define PROTOCOL_CLASS_LENGTH                   1
170 #define RECEIVE_SEQUENCE_NUMBER_LENGTH          1
171 #define CREDIT_LENGTH                           1
172 #define RELEASE_CAUSE_LENGTH                    1
173 #define RETURN_CAUSE_LENGTH                     1
174 #define RESET_CAUSE_LENGTH                      1
175 #define ERROR_CAUSE_LENGTH                      1
176 #define REFUSAL_CAUSE_LENGTH                    1
177 #define HOP_COUNTER_LENGTH                      1
178 #define IMPORTANCE_LENGTH                       1
179
180
181 /* Parts of the Called and Calling Address parameters */
182 /* Address Indicator */
183 #define ADDRESS_INDICATOR_LENGTH        1
184 #define ITU_RESERVED_MASK               0x80
185 #define ANSI_NATIONAL_MASK              0x80
186 #define ROUTING_INDICATOR_MASK          0x40
187 #define GTI_MASK                        0x3C
188 #define GTI_SHIFT                       2
189 #define ITU_SSN_INDICATOR_MASK          0x02
190 #define ITU_PC_INDICATOR_MASK           0x01
191 #define ANSI_PC_INDICATOR_MASK          0x02
192 #define ANSI_SSN_INDICATOR_MASK         0x01
193
194 static const value_string sccp_national_indicator_values[] = {
195   { 0x0,  "Address coded to International standard" },
196   { 0x1,  "Address coded to National standard" },
197   { 0,    NULL } };
198
199 static const value_string sccp_routing_indicator_values[] = {
200   { 0x0, "Route on GT" },
201   { 0x1, "Route on SSN" },
202   { 0,   NULL } };
203
204 #define AI_GTI_NO_GT            0x0
205 #define ITU_AI_GTI_NAI          0x1
206 #define AI_GTI_TT               0x2
207 #define ITU_AI_GTI_TT_NP_ES     0x3
208 #define ITU_AI_GTI_TT_NP_ES_NAI 0x4
209 static const value_string sccp_itu_global_title_indicator_values[] = {
210   { AI_GTI_NO_GT,               "No Global Title" },
211   { ITU_AI_GTI_NAI,             "Nature of Address Indicator only" },
212   { AI_GTI_TT,                  "Translation Type only" },
213   { ITU_AI_GTI_TT_NP_ES,        "Translation Type, Numbering Plan, and Encoding Scheme included" },
214   { ITU_AI_GTI_TT_NP_ES_NAI,    "Translation Type, Numbering Plan, Encoding Scheme, and Nature of Address Indicator included" },
215   { 0,                          NULL } };
216
217 /* #define AI_GTI_NO_GT         0x0 */
218 #define ANSI_AI_GTI_TT_NP_ES    0x1
219 /* #define AI_GTI_TT            0x2 */
220 static const value_string sccp_ansi_global_title_indicator_values[] = {
221   { AI_GTI_NO_GT,               "No Global Title" },
222   { ANSI_AI_GTI_TT_NP_ES,       "Translation Type, Numbering Plan, and Encoding Scheme included" },
223   { AI_GTI_TT,                  "Translation Type only" },
224   { 0,                          NULL } };
225
226 static const value_string sccp_ai_pci_values[] = {
227   { 0x1,  "Point Code present" },
228   { 0x0,  "Point Code not present" },
229   { 0,    NULL } };
230
231 static const value_string sccp_ai_ssni_values[] = {
232   { 0x1,  "SSN present" },
233   { 0x0,  "SSN not present" },
234   { 0,    NULL } };
235
236 #define ADDRESS_SSN_LENGTH    1
237 #define INVALID_SSN 0xff
238   /* Some values from 3GPP TS 23.003 */
239   /*  Japan TTC and NTT define a lot of SSNs, some of which conflict with
240    *  these.  They are not added for now.
241    */
242 static const value_string sccp_ssn_values[] = {
243   { 0x00,  "SSN not known/not used" },
244   { 0x01,  "SCCP management" },
245   { 0x02,  "Reserved for ITU-T allocation" },
246   { 0x03,  "ISDN User Part" },
247   { 0x04,  "OMAP (Operation, Maintenance, and Administration Part)" },
248   { 0x05,  "MAP (Mobile Application Part)" },
249   { 0x06,  "HLR (Home Location Register)" },
250   { 0x07,  "VLR (Visitor Location Register)" },
251   { 0x08,  "MSC (Mobile Switching Center)" },
252   { 0x09,  "EIC/EIR (Equipment Identifier Center/Equipment Identification Register)" },
253   { 0x0a,  "AUC/AC (Authentication Center)" },
254   { 0x0b,  "ISDN supplementary services (ITU only)" },
255   { 0x0c,  "Reserved for international use (ITU only)" },
256   { 0x0d,  "Broadband ISDN edge-to-edge applications (ITU only)" },
257   { 0x0e,  "TC test responder (ITU only)" },
258   /* The following national network subsystem numbers have been allocated for use within and
259    * between GSM/UMTS networks:
260    */
261   { 0x8e,  "RANAP" },
262   { 0x8f,  "RNSAP" },
263   { 0x91,  "GMLC(MAP)" },
264   { 0x92,  "CAP" },
265   { 0x93,  "gsmSCF (MAP) or IM-SSF (MAP) or Presence Network Agent" },
266   { 0x94,  "SIWF (MAP)" },
267   { 0x95,  "SGSN (MAP)" },
268   { 0x96,  "GGSN (MAP)" },
269   /* The following national network subsystem numbers have been allocated for use within GSM/UMTS networks:*/
270   { 0xf9,  "PCAP" },
271   { 0xfa,  "BSC (BSSAP-LE)" },
272   { 0xfb,  "MSC (BSSAP-LE)" },
273   { 0xfc,  "IOS or SMLC (BSSAP-LE)" },
274   { 0xfd,  "BSS O&M (A interface)" },
275   { 0xfe,  "BSSAP/BSAP" },
276   { 0,     NULL } };
277
278
279 /* * * * * * * * * * * * * * * * *
280  * Global Title: ITU GTI == 0001 *
281  * * * * * * * * * * * * * * * * */
282 #define GT_NAI_MASK 0x7F
283 #define GT_NAI_LENGTH 1
284 static const value_string sccp_nai_values[] = {
285   { 0x00,  "NAI unknown" },
286   { 0x01,  "Subscriber Number" },
287   { 0x02,  "Reserved for national use" },
288   { 0x03,  "National significant number" },
289   { 0x04,  "International number" },
290   { 0,     NULL } };
291
292
293 #define GT_OE_MASK 0x80
294 #define GT_OE_EVEN 0
295 #define GT_OE_ODD  1
296 static const value_string sccp_oe_values[] = {
297   { GT_OE_EVEN, "Even number of address signals" },
298   { GT_OE_ODD,  "Odd number of address signals" },
299   { 0,          NULL } };
300
301 #define GT_SIGNAL_LENGTH     1
302 #define GT_ODD_SIGNAL_MASK   0x0f
303 #define GT_EVEN_SIGNAL_MASK  0xf0
304 #define GT_EVEN_SIGNAL_SHIFT 4
305 #define GT_MAX_SIGNALS (32*7)   /* its a bit big, but it allows for adding a lot of "(spare)" and "Unknown" values (7 chars) if there are errors - e.g. ANSI vs ITU wrongly selected */
306 static const value_string sccp_address_signal_values[] = {
307   { 0,  "0" },
308   { 1,  "1" },
309   { 2,  "2" },
310   { 3,  "3" },
311   { 4,  "4" },
312   { 5,  "5" },
313   { 6,  "6" },
314   { 7,  "7" },
315   { 8,  "8" },
316   { 9,  "9" },
317   { 10, "(spare)" },
318   { 11, "11" },
319   { 12, "12" },
320   { 13, "(spare)" },
321   { 14, "(spare)" },
322   { 15, "ST" },
323   { 0,  NULL } };
324
325
326 /* * * * * * * * * * * * * * * * * * * * *
327  * Global Title: ITU and ANSI GTI == 0010 *
328  * * * * * * * * * * * * * * * * * * * * */
329 #define GT_TT_LENGTH 1
330
331
332 /* * * * * * * * * * * * * * * * * * * * * * * * * *
333  * Global Title: ITU GTI == 0011, ANSI GTI == 0001 *
334  * * * * * * * * * * * * * * * * * * * * * * * * * */
335 #define GT_NP_MASK 0xf0
336 #define GT_NP_ES_LENGTH 1
337 static const value_string sccp_np_values[] = {
338   { 0x0,  "Unknown" },
339   { 0x1,  "ISDN/telephony" },
340   { 0x2,  "Generic (ITU)/Reserved (ANSI)" },
341   { 0x3,  "Data" },
342   { 0x4,  "Telex" },
343   { 0x5,  "Maritime mobile" },
344   { 0x6,  "Land mobile" },
345   { 0x7,  "ISDN/mobile" },
346   { 0xe,  "Private network or network-specific" },
347   { 0xf,  "Reserved" },
348   { 0,    NULL } };
349
350 #define GT_ES_MASK     0x0f
351 #define GT_ES_UNKNOWN  0x0
352 #define GT_ES_BCD_ODD  0x1
353 #define GT_ES_BCD_EVEN 0x2
354 #define GT_ES_NATIONAL 0x3
355 #define GT_ES_RESERVED 0xf
356 static const value_string sccp_es_values[] = {
357   { GT_ES_UNKNOWN,      "Unknown" },
358   { GT_ES_BCD_ODD,      "BCD, odd number of digits" },
359   { GT_ES_BCD_EVEN,     "BCD, even number of digits" },
360   { GT_ES_NATIONAL,     "National specific" },
361   { GT_ES_RESERVED,     "Reserved (ITU)/Spare (ANSI)" },
362   { 0,                  NULL } };
363
364 /* Address signals above */
365
366
367 /* * * * * * * * * * * * * * * * *
368  * Global Title: ITU GTI == 0100 *
369  * * * * * * * * * * * * * * * * */
370 /* NP above */
371 /* ES above */
372 /* NAI above */
373 /* Address signals above */
374
375
376 #define CLASS_CLASS_MASK 0xf
377 #define CLASS_SPARE_HANDLING_MASK 0xf0
378 static const value_string sccp_class_handling_values [] = {
379   { 0x0,  "No special options" },
380   { 0x8,  "Return message on error" },
381   { 0,    NULL } };
382
383
384 #define SEGMENTING_REASSEMBLING_LENGTH 1
385 #define SEGMENTING_REASSEMBLING_MASK   0x01
386 #define NO_MORE_DATA 0
387 #define MORE_DATA    1
388 /* This is also used by sequencing-segmenting parameter */
389 static const value_string sccp_segmenting_reassembling_values [] = {
390   { NO_MORE_DATA,       "No more data" },
391   { MORE_DATA,          "More data" },
392   { 0,                  NULL } };
393
394
395 #define RECEIVE_SEQUENCE_NUMBER_LENGTH  1
396 #define RSN_MASK                        0xfe
397
398 #define SEQUENCING_SEGMENTING_LENGTH            2
399 #define SEQUENCING_SEGMENTING_SSN_LENGTH        1
400 #define SEQUENCING_SEGMENTING_RSN_LENGTH        1
401 #define SEND_SEQUENCE_NUMBER_MASK               0xfe
402 #define RECEIVE_SEQUENCE_NUMBER_MASK            0xfe
403 #define SEQUENCING_SEGMENTING_MORE_MASK         0x01
404
405
406 #define CREDIT_LENGTH 1
407
408 #define RELEASE_CAUSE_LENGTH 1
409 static const value_string sccp_release_cause_values [] = {
410   { 0x00,  "End user originated" },
411   { 0x01,  "End user congestion" },
412   { 0x02,  "End user failure" },
413   { 0x03,  "SCCP user originated" },
414   { 0x04,  "Remote procedure error" },
415   { 0x05,  "Inconsistent connection data" },
416   { 0x06,  "Access failure" },
417   { 0x07,  "Access congestion" },
418   { 0x08,  "Subsystem failure" },
419   { 0x09,  "Subsystem congestion" },
420   { 0x0a,  "MTP failure" },
421   { 0x0b,  "Netowrk congestion" },
422   { 0x0c,  "Expiration of reset timer" },
423   { 0x0d,  "Expiration of receive inactivity timer" },
424   { 0x0e,  "Reserved" },
425   { 0x0f,  "Unqualified" },
426   { 0x10,  "SCCP failure (ITU only)" },
427   { 0,     NULL } };
428
429
430 #define RETURN_CAUSE_LENGTH 1
431 static const value_string sccp_return_cause_values [] = {
432   { 0x00,  "No translation for an address of such nature" },
433   { 0x01,  "No translation for this specific address" },
434   { 0x02,  "Subsystem congestion" },
435   { 0x03,  "Subsystem failure" },
436   { 0x04,  "Unequipped failure" },
437   { 0x05,  "MTP failure" },
438   { 0x06,  "Network congestion" },
439   { 0x07,  "Unqualified" },
440   { 0x08,  "Error in message transport" },
441   { 0x09,  "Error in local processing" },
442   { 0x0a,  "Destination cannot perform reassembly" },
443   { 0x0b,  "SCCP failure" },
444   { 0x0c,  "Hop counter violation" },
445   { 0x0d,  "Segmentation not supported (ITU only)" },
446   { 0x0e,  "Segmentation failure (ITU only)" },
447   { 0xf9,  "Invalid ISNI routing request (ANSI only)"},
448   { 0xfa,  "Unauthorized message (ANSI only)" },
449   { 0xfb,  "Message incompatibility (ANSI only)" },
450   { 0xfc,  "Cannot perform ISNI constrained routing (ANSI only)" },
451   { 0xfd,  "Unable to perform ISNI identification (ANSI only)" },
452   { 0,     NULL } };
453
454
455 #define RESET_CAUSE_LENGTH 1
456 static const value_string sccp_reset_cause_values [] = {
457   { 0x00,  "End user originated" },
458   { 0x01,  "SCCP user originated" },
459   { 0x02,  "Message out of order - incorrect send sequence number" },
460   { 0x03,  "Message out of order - incorrect receive sequence number" },
461   { 0x04,  "Remote procedure error - message out of window" },
462   { 0x05,  "Remote procedure error - incorrect send sequence number after (re)initialization" },
463   { 0x06,  "Remote procedure error - general" },
464   { 0x07,  "Remote end user operational" },
465   { 0x08,  "Network operational" },
466   { 0x09,  "Access operational" },
467   { 0x0a,  "Network congestion" },
468   { 0x0b,  "Reserved (ITU)/Not obtainable (ANSI)" },
469   { 0x0c,  "Unqualified" },
470   { 0,     NULL } };
471
472
473 #define ERROR_CAUSE_LENGTH 1
474 static const value_string sccp_error_cause_values [] = {
475   { 0x00,  "Local Reference Number (LRN) mismatch - unassigned destination LRN" },
476   { 0x01,  "Local Reference Number (LRN) mismatch - inconsistent source LRN" },
477   { 0x02,  "Point code mismatch" },
478   { 0x03,  "Service class mismatch" },
479   { 0x04,  "Unqualified" },
480   { 0,     NULL } };
481
482
483 #define REFUSAL_CAUSE_LENGTH 1
484 static const value_string sccp_refusal_cause_values [] = {
485   { 0x00,  "End user originated" },
486   { 0x01,  "End user congestion" },
487   { 0x02,  "End user failure" },
488   { 0x03,  "SCCP user originated" },
489   { 0x04,  "Destination address unknown" },
490   { 0x05,  "Destination inaccessible" },
491   { 0x06,  "Network resource - QOS not available/non-transient" },
492   { 0x07,  "Network resource - QOS not available/transient" },
493   { 0x08,  "Access failure" },
494   { 0x09,  "Access congestion" },
495   { 0x0a,  "Subsystem failure" },
496   { 0x0b,  "Subsystem congestion" },
497   { 0x0c,  "Expiration of connection establishment timer" },
498   { 0x0d,  "Incompatible user data" },
499   { 0x0e,  "Reserved" },
500   { 0x0f,  "Unqualified" },
501   { 0x10,  "Hop counter violation" },
502   { 0x11,  "SCCP failure (ITU only)" },
503   { 0x12,  "No translation for an address of such nature" },
504   { 0x13,  "Unequipped user" },
505   { 0,     NULL } };
506
507
508 #define SEGMENTATION_LENGTH             4
509 #define SEGMENTATION_FIRST_SEGMENT_MASK 0x80
510 #define SEGMENTATION_CLASS_MASK         0x40
511 #define SEGMENTATION_SPARE_MASK         0x30
512 #define SEGMENTATION_REMAINING_MASK     0x0f
513 static const value_string sccp_segmentation_first_segment_values [] = {
514   { 1,  "First segment" },
515   { 0,  "Not first segment" },
516   { 0,  NULL } };
517 static const value_string sccp_segmentation_class_values [] = {
518   { 0,  "Class 0 selected" },
519   { 1,  "Class 1 selected" },
520   { 0,  NULL } };
521
522
523 #define HOP_COUNTER_LENGTH 1
524
525 #define IMPORTANCE_LENGTH               1
526 #define IMPORTANCE_IMPORTANCE_MASK      0x7
527
528
529 #define ANSI_ISNI_ROUTING_CONTROL_LENGTH 1
530 #define ANSI_ISNI_MI_MASK                0x01
531 #define ANSI_ISNI_IRI_MASK               0x06
532 #define ANSI_ISNI_RES_MASK               0x08
533 #define ANSI_ISNI_TI_MASK                0x10
534 #define ANSI_ISNI_TI_SHIFT               4
535 #define ANSI_ISNI_COUNTER_MASK           0xe0
536 #define ANSI_ISNI_NETSPEC_MASK           0x03
537
538 static const value_string sccp_isni_mark_for_id_values [] = {
539   { 0x0,  "Do not identify networks" },
540   { 0x1,  "Identify networks" },
541   { 0,    NULL } };
542
543 static const value_string sccp_isni_iri_values [] = {
544   { 0x0,  "Neither constrained nor suggested ISNI routing" },
545   { 0x1,  "Constrained ISNI routing" },
546   { 0x2,  "Reserved for suggested ISNI routing" },
547   { 0x3,  "Spare" },
548   { 0,    NULL } };
549
550 #define ANSI_ISNI_TYPE_0 0x0
551 #define ANSI_ISNI_TYPE_1 0x1
552 static const value_string sccp_isni_ti_values [] = {
553   { ANSI_ISNI_TYPE_0,   "Type zero ISNI parameter format" },
554   { ANSI_ISNI_TYPE_1,   "Type one ISNI parameter format" },
555   { 0,                  NULL } };
556
557
558 /* Initialize the protocol and registered fields */
559 static int proto_sccp = -1;
560 static int hf_sccp_message_type = -1;
561 static int hf_sccp_variable_pointer1 = -1;
562 static int hf_sccp_variable_pointer2 = -1;
563 static int hf_sccp_variable_pointer3 = -1;
564 static int hf_sccp_optional_pointer = -1;
565 static int hf_sccp_ssn = -1;
566 static int hf_sccp_gt_digits = -1;
567
568 /* Called Party address */
569 static int hf_sccp_called_national_indicator = -1;
570 static int hf_sccp_called_routing_indicator = -1;
571 static int hf_sccp_called_itu_global_title_indicator = -1;
572 static int hf_sccp_called_ansi_global_title_indicator = -1;
573 static int hf_sccp_called_itu_ssn_indicator = -1;
574 static int hf_sccp_called_itu_point_code_indicator = -1;
575 static int hf_sccp_called_ansi_ssn_indicator = -1;
576 static int hf_sccp_called_ansi_point_code_indicator = -1;
577 static int hf_sccp_called_ssn = -1;
578 static int hf_sccp_called_pc_member = -1;
579 static int hf_sccp_called_pc_cluster = -1;
580 static int hf_sccp_called_pc_network = -1;
581 static int hf_sccp_called_ansi_pc = -1;
582 static int hf_sccp_called_chinese_pc = -1;
583 static int hf_sccp_called_itu_pc = -1;
584 static int hf_sccp_called_japan_pc = -1;
585 static int hf_sccp_called_gt_nai = -1;
586 static int hf_sccp_called_gt_oe = -1;
587 static int hf_sccp_called_gt_tt = -1;
588 static int hf_sccp_called_gt_np = -1;
589 static int hf_sccp_called_gt_es = -1;
590 static int hf_sccp_called_gt_digits = -1;
591
592 /* Calling party address */
593 static int hf_sccp_calling_national_indicator = -1;
594 static int hf_sccp_calling_routing_indicator = -1;
595 static int hf_sccp_calling_itu_global_title_indicator = -1;
596 static int hf_sccp_calling_ansi_global_title_indicator = -1;
597 static int hf_sccp_calling_itu_ssn_indicator = -1;
598 static int hf_sccp_calling_itu_point_code_indicator = -1;
599 static int hf_sccp_calling_ansi_ssn_indicator = -1;
600 static int hf_sccp_calling_ansi_point_code_indicator = -1;
601 static int hf_sccp_calling_ssn = -1;
602 static int hf_sccp_calling_pc_member = -1;
603 static int hf_sccp_calling_pc_cluster = -1;
604 static int hf_sccp_calling_pc_network = -1;
605 static int hf_sccp_calling_ansi_pc = -1;
606 static int hf_sccp_calling_chinese_pc = -1;
607 static int hf_sccp_calling_itu_pc = -1;
608 static int hf_sccp_calling_japan_pc = -1;
609 static int hf_sccp_calling_gt_nai = -1;
610 static int hf_sccp_calling_gt_oe = -1;
611 static int hf_sccp_calling_gt_tt = -1;
612 static int hf_sccp_calling_gt_np = -1;
613 static int hf_sccp_calling_gt_es = -1;
614 static int hf_sccp_calling_gt_digits = -1;
615
616 /* Other parameter values */
617 static int hf_sccp_dlr = -1;
618 static int hf_sccp_slr = -1;
619 static int hf_sccp_lr = -1;
620 static int hf_sccp_class = -1;
621 static int hf_sccp_handling = -1;
622 static int hf_sccp_more = -1;
623 static int hf_sccp_rsn = -1;
624 static int hf_sccp_sequencing_segmenting_ssn = -1;
625 static int hf_sccp_sequencing_segmenting_rsn = -1;
626 static int hf_sccp_sequencing_segmenting_more = -1;
627 static int hf_sccp_credit = -1;
628 static int hf_sccp_release_cause = -1;
629 static int hf_sccp_return_cause = -1;
630 static int hf_sccp_reset_cause = -1;
631 static int hf_sccp_error_cause = -1;
632 static int hf_sccp_refusal_cause = -1;
633 static int hf_sccp_segmentation_first = -1;
634 static int hf_sccp_segmentation_class = -1;
635 static int hf_sccp_segmentation_remaining = -1;
636 static int hf_sccp_segmentation_slr = -1;
637 static int hf_sccp_hop_counter = -1;
638 static int hf_sccp_importance = -1;
639 static int hf_sccp_ansi_isni_mi = -1;
640 static int hf_sccp_ansi_isni_iri = -1;
641 static int hf_sccp_ansi_isni_ti = -1;
642 static int hf_sccp_ansi_isni_netspec = -1;
643 static int hf_sccp_ansi_isni_counter = -1;
644 static int hf_sccp_xudt_msg_fragments = -1;
645 static int hf_sccp_xudt_msg_fragment = -1;
646 static int hf_sccp_xudt_msg_fragment_overlap = -1;
647 static int hf_sccp_xudt_msg_fragment_overlap_conflicts = -1;
648 static int hf_sccp_xudt_msg_fragment_multiple_tails = -1;
649 static int hf_sccp_xudt_msg_fragment_too_long_fragment = -1;
650 static int hf_sccp_xudt_msg_fragment_error = -1;
651 static int hf_sccp_xudt_msg_reassembled_in = -1;
652 static int hf_sccp_assoc_msg = -1;
653 static int hf_sccp_assoc_id = -1;
654
655 /* Initialize the subtree pointers */
656 static gint ett_sccp = -1;
657 static gint ett_sccp_called = -1;
658 static gint ett_sccp_called_ai = -1;
659 static gint ett_sccp_called_pc = -1;
660 static gint ett_sccp_called_gt = -1;
661 static gint ett_sccp_calling = -1;
662 static gint ett_sccp_calling_ai = -1;
663 static gint ett_sccp_calling_pc = -1;
664 static gint ett_sccp_calling_gt = -1;
665 static gint ett_sccp_sequencing_segmenting = -1;
666 static gint ett_sccp_segmentation = -1;
667 static gint ett_sccp_ansi_isni_routing_control = -1;
668 static gint ett_sccp_xudt_msg_fragment = -1;
669 static gint ett_sccp_xudt_msg_fragments = -1;
670 static gint ett_sccp_assoc = -1;
671
672 /* Declarations to desegment XUDT Messages */
673 static gboolean sccp_xudt_desegment = TRUE;
674
675 static gboolean show_key_params = FALSE;
676
677 static int sccp_tap = -1;
678
679
680 static const fragment_items sccp_xudt_msg_frag_items = {
681         /* Fragment subtrees */
682         &ett_sccp_xudt_msg_fragment,
683         &ett_sccp_xudt_msg_fragments,
684         /* Fragment fields */
685         &hf_sccp_xudt_msg_fragments,
686         &hf_sccp_xudt_msg_fragment,
687         &hf_sccp_xudt_msg_fragment_overlap,
688         &hf_sccp_xudt_msg_fragment_overlap_conflicts,
689         &hf_sccp_xudt_msg_fragment_multiple_tails,
690         &hf_sccp_xudt_msg_fragment_too_long_fragment,
691         &hf_sccp_xudt_msg_fragment_error,
692         /* Reassembled in field */
693         &hf_sccp_xudt_msg_reassembled_in,
694         /* Tag */
695         "SCCP XUDT Message fragments"
696 };
697
698 static GHashTable *sccp_xudt_msg_fragment_table = NULL;
699 static GHashTable *sccp_xudt_msg_reassembled_table = NULL;
700
701
702
703 /*
704  * Here are the global variables associated with
705  * the various user definable characteristics of the dissection
706  */
707 static guint32 sccp_source_pc_global = 0;
708 static gboolean sccp_show_length = FALSE;
709
710 static module_t *sccp_module;
711 static heur_dissector_list_t heur_subdissector_list;
712
713 /*  Keep track of SSN value of current message so if/when we get to the data
714  *  parameter, we can call appropriate sub-dissector.  TODO: can this info
715  *  be stored elsewhere?
716  */
717
718 static guint8 message_type = 0;
719 static guint dlr = 0;
720 static guint slr = 0;
721
722 static dissector_handle_t data_handle;
723 static dissector_table_t sccp_ssn_dissector_table;
724
725 static emem_tree_t* assocs = NULL;
726 static sccp_assoc_info_t* assoc;
727 static sccp_assoc_info_t no_assoc = {0,0,0,0,0,FALSE,FALSE,NULL,NULL,SCCP_PLOAD_NONE,NULL,NULL,NULL};
728 static gboolean trace_sccp = FALSE;
729 static guint32 next_assoc_id = 0;
730
731 static const value_string assoc_protos[] = {
732         {  SCCP_PLOAD_BSSAP, "BSSAP" },
733         {  SCCP_PLOAD_RANAP, "RANAP" },
734         { 0 , NULL }
735 };
736
737 static sccp_assoc_info_t* new_assoc(guint32 calling, guint32 called){
738         sccp_assoc_info_t* a = se_alloc(sizeof(sccp_assoc_info_t));
739
740         a->id = next_assoc_id++;
741         a->calling_dpc = calling;
742         a->called_dpc = called;
743         a->calling_ssn = INVALID_SSN;
744         a->called_ssn = INVALID_SSN;
745         a->has_fw_key = FALSE;
746         a->has_bw_key = FALSE;
747         a->payload = SCCP_PLOAD_NONE;
748         a->calling_party = NULL;
749         a->called_party = NULL;
750         a->extra_info = NULL;
751         a->msgs = NULL;
752
753         return a;                               
754 }
755
756 sccp_assoc_info_t* get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_lr, guint32 dst_lr, guint msg_type) {
757     guint32 opck, dpck;
758     address* opc = &(pinfo->src);
759     address* dpc = &(pinfo->dst);
760     guint framenum = pinfo->fd->num;
761         
762     if (assoc)
763                 return assoc;
764         
765     if (!src_lr && !dst_lr){
766                 return &no_assoc;
767     }
768         
769     opck = opc->type == AT_SS7PC ? mtp3_pc_hash(opc->data) : g_str_hash(address_to_str(opc));
770     dpck = dpc->type == AT_SS7PC ? mtp3_pc_hash(dpc->data) : g_str_hash(address_to_str(dpc));
771         
772         
773     switch (msg_type) {
774                 case SCCP_MSG_TYPE_CR:
775                 {
776                         /* CR contains the opc,dpc,dlr key of backward messages swapped as dpc,opc,slr  */
777                         emem_tree_key_t bw_key[] = {
778                                 {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL}
779                         };
780
781                         if (! ( assoc = se_tree_lookup32_array(assocs,bw_key) ) && ! pinfo->fd->flags.visited ) {
782                                 assoc = new_assoc(opck,dpck);
783                                 se_tree_insert32_array(assocs,bw_key,assoc);
784                                 assoc->has_bw_key = TRUE;
785                         }
786                         break;
787                 }
788                 case SCCP_MSG_TYPE_CC:
789                 {
790                         emem_tree_key_t fw_key[] = {
791                                 {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL}
792                         };
793                         emem_tree_key_t bw_key[] = {
794                                 {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
795                         };
796
797                         if ( ( assoc = se_tree_lookup32_array(assocs,bw_key) ) ) {
798                                 goto got_assoc;
799                         } 
800                         
801                         if ( (assoc = se_tree_lookup32_array(assocs,fw_key) ) ) {
802                                 goto got_assoc;                         
803                         }
804                         
805                         assoc = new_assoc(opck,dpck);
806
807          got_assoc:
808                         if ( ! pinfo->fd->flags.visited && ! assoc->has_bw_key ) {
809
810                                 se_tree_insert32_array(assocs,bw_key,assoc);
811                                 assoc->has_bw_key = TRUE;
812                         }
813                         
814                         if ( ! pinfo->fd->flags.visited && ! assoc->has_fw_key ) {
815                                 se_tree_insert32_array(assocs,fw_key,assoc);
816                                 assoc->has_fw_key = TRUE;
817                         }
818
819                         break;
820                 }
821                 default:
822                 {
823                         emem_tree_key_t key[] = {
824                                 {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
825                         };
826                         
827                         assoc = se_tree_lookup32_array(assocs,key);
828
829                         break;
830                 }
831     }
832         
833         if (assoc && trace_sccp) {
834             if ( ! pinfo->fd->flags.visited) {
835                         sccp_msg_info_t* msg = se_alloc(sizeof(sccp_msg_info_t));
836                         msg->framenum = framenum;
837                         msg->offset = offset;
838                         msg->next = NULL;
839                         msg->assoc = assoc;
840                         msg->label = NULL;
841                         msg->comment = NULL;
842                         msg->type = msg_type;
843                         
844                         if (assoc->msgs) {
845                                 sccp_msg_info_t* m;
846                                 for (m = assoc->msgs; m->next; m = m->next) ;
847                                 m->next = msg;
848                         } else {
849                                 assoc->msgs = msg;
850                         }
851                         
852                         assoc->curr_msg = msg;
853                         
854             } else {
855                         
856                         sccp_msg_info_t* m;
857                         
858                         for (m = assoc->msgs; m; m = m->next) {
859                                 if (m->framenum == framenum && m->offset == offset) {
860                                         assoc->curr_msg = m;
861                                         break;
862                                 }
863                         }
864                 }
865         }
866         
867         return assoc ? assoc : &no_assoc;
868 }
869
870
871 static void
872 dissect_sccp_unknown_message(tvbuff_t *message_tvb, proto_tree *sccp_tree)
873 {
874   guint32 message_length;
875
876   message_length = tvb_length(message_tvb);
877
878   proto_tree_add_text(sccp_tree, message_tvb, 0, message_length,
879                       "Unknown message (%u byte%s)",
880                       message_length, plurality(message_length, "", "s"));
881 }
882
883 static void
884 dissect_sccp_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint length)
885 {
886   proto_tree_add_text(tree, tvb, 0, length, "Unknown parameter 0x%x (%u byte%s)",
887                       type, length, plurality(length, "", "s"));
888 }
889
890 static void
891 dissect_sccp_dlr_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
892 {
893   proto_item* lr_item;
894
895   dlr = tvb_get_letoh24(tvb, 0);
896   proto_tree_add_uint(tree, hf_sccp_dlr, tvb, 0, length, dlr);
897   lr_item = proto_tree_add_uint(tree, hf_sccp_lr, tvb, 0, length, dlr);
898   PROTO_ITEM_SET_HIDDEN(lr_item);
899
900   if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
901     col_append_fstr(pinfo->cinfo, COL_INFO, "DLR=%ld ", dlr);
902 }
903
904 static void
905 dissect_sccp_slr_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
906 {
907   proto_item* lr_item;
908
909   slr = tvb_get_letoh24(tvb, 0);
910   proto_tree_add_uint(tree, hf_sccp_slr, tvb, 0, length, slr);
911   lr_item = proto_tree_add_uint(tree, hf_sccp_lr, tvb, 0, length, slr);
912   PROTO_ITEM_SET_HIDDEN(lr_item);
913
914   if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
915     col_append_fstr(pinfo->cinfo, COL_INFO, "SLR=%ld ", slr);
916 }
917
918 static void
919 dissect_sccp_gt_address_information(tvbuff_t *tvb, proto_tree *tree,
920                                     guint length, gboolean even_length,
921                                     gboolean called)
922 {
923   guint offset = 0;
924   guint8 odd_signal, even_signal = 0x0f;
925   char gt_digits[GT_MAX_SIGNALS+1] = { 0 };
926
927   while(offset < length)
928   {
929     odd_signal = tvb_get_guint8(tvb, offset) & GT_ODD_SIGNAL_MASK;
930     even_signal = tvb_get_guint8(tvb, offset) & GT_EVEN_SIGNAL_MASK;
931     even_signal >>= GT_EVEN_SIGNAL_SHIFT;
932
933     strncat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values,
934                                  "Unknown"), GT_MAX_SIGNALS - strlen(gt_digits));
935
936     /* If the last signal is NOT filler */
937     if (offset != (length - 1) || even_length == TRUE)
938       strncat(gt_digits, val_to_str(even_signal, sccp_address_signal_values,
939                                    "Unknown"), GT_MAX_SIGNALS - strlen(gt_digits));
940
941     offset += GT_SIGNAL_LENGTH;
942   }
943
944   proto_tree_add_string_format(tree, called ? hf_sccp_called_gt_digits
945                                             : hf_sccp_calling_gt_digits,
946                              tvb, 0, length, gt_digits,
947                              "Address information (digits): %s", gt_digits);
948   proto_tree_add_string_hidden(tree, called ? hf_sccp_gt_digits
949                                             : hf_sccp_gt_digits,
950                                tvb, 0, length, gt_digits);
951 }
952
953 static void
954 dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint length,
955                           guint8 gti, gboolean called)
956 {
957   proto_item *gt_item = 0;
958   proto_tree *gt_tree = 0;
959   tvbuff_t *signals_tvb;
960   guint offset = 0;
961   guint8 odd_even, nai, tt, np, es;
962   gboolean even = TRUE;
963
964   /* Shift GTI to where we can work with it */
965   gti >>= GTI_SHIFT;
966
967   gt_item = proto_tree_add_text(tree, tvb, offset, length,
968                                 "Global Title 0x%x (%u byte%s)",
969                                 gti, length, plurality(length,"", "s"));
970   gt_tree = proto_item_add_subtree(gt_item, called ? ett_sccp_called_gt
971                                                    : ett_sccp_calling_gt);
972
973   /* Decode Transation Type (if present) */
974   switch (gti) {
975   case AI_GTI_TT:
976
977     /* Protocol doesn't tell us, so we ASSUME even... */
978     even = TRUE;
979     /* Fall through */
980   case ITU_AI_GTI_TT_NP_ES:
981   case ITU_AI_GTI_TT_NP_ES_NAI:
982   case ANSI_AI_GTI_TT_NP_ES:
983
984     tt = tvb_get_guint8(tvb, offset);
985     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_tt
986                                         : hf_sccp_calling_gt_tt,
987                         tvb, offset, GT_TT_LENGTH, tt);
988     offset += GT_TT_LENGTH;
989   }
990
991   /* Decode Numbering Plan and Encoding Scheme (if present) */
992   switch (gti) {
993   case ITU_AI_GTI_TT_NP_ES:
994   case ITU_AI_GTI_TT_NP_ES_NAI:
995   case ANSI_AI_GTI_TT_NP_ES:
996
997     np = tvb_get_guint8(tvb, offset) & GT_NP_MASK;
998     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_np
999                                         : hf_sccp_calling_gt_np,
1000                         tvb, offset, GT_NP_ES_LENGTH, np);
1001
1002     es = tvb_get_guint8(tvb, offset) & GT_ES_MASK;
1003     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_es
1004                                         : hf_sccp_calling_gt_es,
1005                         tvb, offset, GT_NP_ES_LENGTH, es);
1006
1007     even = (es == GT_ES_BCD_EVEN) ? TRUE : FALSE;
1008
1009     offset += GT_NP_ES_LENGTH;
1010   }
1011
1012   /* Decode Odd/Even Indicator (if present) */
1013   if (gti == ITU_AI_GTI_NAI) {
1014     odd_even = tvb_get_guint8(tvb, offset) & GT_OE_MASK;
1015     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_oe
1016                                         : hf_sccp_calling_gt_oe,
1017                         tvb, offset, GT_NAI_LENGTH, odd_even);
1018     even = (odd_even == GT_OE_EVEN) ? TRUE : FALSE;
1019
1020     /* offset doesn't change */
1021   }
1022
1023   /* Decode Nature of Address Indicator (if present) */
1024   switch (gti) {
1025   case ITU_AI_GTI_NAI:
1026   case ITU_AI_GTI_TT_NP_ES_NAI:
1027     nai = tvb_get_guint8(tvb, offset) & GT_NAI_MASK;
1028     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_nai
1029                                         : hf_sccp_calling_gt_nai,
1030                         tvb, offset, GT_NAI_LENGTH, nai);
1031
1032     offset += GT_NAI_LENGTH;
1033   }
1034
1035   /* Decode address signal(s) */
1036   if (length < offset)
1037     return;
1038
1039   signals_tvb = tvb_new_subset(tvb, offset, (length - offset),
1040                                (length - offset));
1041   dissect_sccp_gt_address_information(signals_tvb, gt_tree, (length - offset),
1042                                       even, called);
1043 }
1044
1045 static int
1046 dissect_sccp_3byte_pc(tvbuff_t *tvb, proto_tree *call_tree, guint offset,
1047                       gboolean called)
1048 {
1049   int *hf_pc;
1050
1051   if (decode_mtp3_standard == ANSI_STANDARD)
1052   {
1053     if (called)
1054       hf_pc = &hf_sccp_called_ansi_pc;
1055     else
1056       hf_pc = &hf_sccp_calling_ansi_pc;
1057   } else /* CHINESE_ITU_STANDARD */ {
1058     if (called)
1059       hf_pc = &hf_sccp_called_chinese_pc;
1060     else
1061       hf_pc = &hf_sccp_calling_chinese_pc;
1062   }
1063
1064   /* create and fill the PC tree */
1065   dissect_mtp3_3byte_pc(tvb, offset, call_tree,
1066                         called ? ett_sccp_called_pc : ett_sccp_calling_pc,
1067                         *hf_pc,
1068                         called ? hf_sccp_called_pc_network : hf_sccp_calling_pc_network,
1069                         called ? hf_sccp_called_pc_cluster : hf_sccp_calling_pc_cluster,
1070                         called ? hf_sccp_called_pc_member  : hf_sccp_calling_pc_member,
1071                         0, 0);
1072
1073   return(offset + ANSI_PC_LENGTH);
1074 }
1075
1076 /*  FUNCTION dissect_sccp_called_calling_param():
1077  *  Dissect the Calling or Called Party Address parameters.
1078  *
1079  *  The boolean 'called' describes whether this function is decoding a
1080  *  called (TRUE) or calling (FALSE) party address.  There is simply too
1081  *  much code in this function to have 2 copies of it (one for called, one
1082  *  for calling).
1083  *
1084  *  NOTE:  this function is called even when (!tree) so that we can get
1085  *  the SSN and subsequently call subdissectors (if and when there's a data
1086  *  parameter).  Realistically we should put if (!tree)'s around a lot of the
1087  *  code, but I think that would make it unreadable--and the expense of not
1088  *  doing so does not appear to be very high.
1089  */
1090 static void
1091 dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree,
1092                                   guint length, gboolean called)
1093 {
1094   proto_item *call_item = 0, *call_ai_item = 0, *item;
1095   proto_tree *call_tree = 0, *call_ai_tree = 0;
1096   guint offset;
1097   guint8 national = -1, routing_ind, gti, pci, ssni, ssn;
1098   tvbuff_t *gt_tvb;
1099   dissector_handle_t ssn_dissector = NULL, tcap_ssn_dissector = NULL;
1100   const char *ssn_dissector_short_name = NULL;
1101   const char *tcap_ssn_dissector_short_name = NULL;
1102
1103   call_item = proto_tree_add_text(tree, tvb, 0, length,
1104                                     "%s Party address (%u byte%s)",
1105                                     called ? "Called" : "Calling", length,
1106                                     plurality(length, "", "s"));
1107   call_tree = proto_item_add_subtree(call_item, called ? ett_sccp_called
1108                                                        : ett_sccp_calling);
1109
1110   call_ai_item = proto_tree_add_text(call_tree, tvb, 0,
1111                                        ADDRESS_INDICATOR_LENGTH,
1112                                        "Address Indicator");
1113   call_ai_tree = proto_item_add_subtree(call_ai_item, called ? ett_sccp_called_ai
1114                                                              : ett_sccp_calling_ai);
1115
1116   if (decode_mtp3_standard == ANSI_STANDARD)
1117   {
1118     national = tvb_get_guint8(tvb, 0) & ANSI_NATIONAL_MASK;
1119     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_national_indicator
1120                                              : hf_sccp_calling_national_indicator,
1121                         tvb, 0, ADDRESS_INDICATOR_LENGTH, national);
1122   }
1123
1124   routing_ind = tvb_get_guint8(tvb, 0) & ROUTING_INDICATOR_MASK;
1125   proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_routing_indicator
1126                                            : hf_sccp_calling_routing_indicator,
1127                       tvb, 0, ADDRESS_INDICATOR_LENGTH, routing_ind);
1128
1129   gti = tvb_get_guint8(tvb, 0) & GTI_MASK;
1130
1131   if (decode_mtp3_standard == ITU_STANDARD ||
1132       decode_mtp3_standard == CHINESE_ITU_STANDARD ||
1133       decode_mtp3_standard == JAPAN_STANDARD ||
1134       national == 0) {
1135
1136     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_global_title_indicator
1137                                              : hf_sccp_called_itu_global_title_indicator,
1138                         tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
1139
1140     ssni = tvb_get_guint8(tvb, 0) & ITU_SSN_INDICATOR_MASK;
1141     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_ssn_indicator
1142                                              : hf_sccp_calling_itu_ssn_indicator,
1143                         tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
1144
1145     pci = tvb_get_guint8(tvb, 0) & ITU_PC_INDICATOR_MASK;
1146     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_point_code_indicator
1147                                              : hf_sccp_calling_itu_point_code_indicator,
1148                         tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
1149
1150     offset = ADDRESS_INDICATOR_LENGTH;
1151
1152     /* Dissect PC (if present) */
1153     if (pci) {
1154       if (decode_mtp3_standard == ITU_STANDARD) {
1155
1156         proto_tree_add_item(call_tree, called ? hf_sccp_called_itu_pc
1157                                               : hf_sccp_calling_itu_pc,
1158                             tvb, offset, ITU_PC_LENGTH, TRUE);
1159
1160         offset += ITU_PC_LENGTH;
1161
1162       } else if (decode_mtp3_standard == JAPAN_STANDARD) {
1163
1164         proto_tree_add_item(call_tree, called ? hf_sccp_called_japan_pc
1165                                               : hf_sccp_calling_japan_pc,
1166                             tvb, offset, JAPAN_PC_LENGTH, TRUE);
1167
1168         offset += JAPAN_PC_LENGTH;
1169
1170       } else /* CHINESE_ITU_STANDARD */ {
1171
1172         offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
1173
1174       }
1175     }
1176
1177     /* Dissect SSN (if present) */
1178     if (ssni) {
1179       ssn = tvb_get_guint8(tvb, offset);
1180
1181       if (called && assoc)
1182         assoc->called_ssn = ssn;
1183       else if (assoc)
1184         assoc->calling_ssn = ssn;
1185
1186       proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
1187                                             : hf_sccp_calling_ssn,
1188                           tvb, offset, ADDRESS_SSN_LENGTH, ssn);
1189       proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
1190                                  ADDRESS_SSN_LENGTH, ssn);
1191       offset += ADDRESS_SSN_LENGTH;
1192
1193       /* Get the dissector handle of the dissector registered for this ssn
1194        * And print it's name.
1195        */
1196       ssn_dissector = dissector_get_port_handle(sccp_ssn_dissector_table, ssn);
1197
1198       if (ssn_dissector) {
1199           ssn_dissector_short_name = dissector_handle_get_short_name(ssn_dissector);
1200
1201           if(ssn_dissector_short_name) {
1202               item = proto_tree_add_text(call_tree, tvb, offset - 1, ADDRESS_SSN_LENGTH, "Linked to %s", ssn_dissector_short_name);
1203               PROTO_ITEM_SET_GENERATED(item);
1204
1205               if (strncasecmp("TCAP", ssn_dissector_short_name, 4)== 0) {
1206                       tcap_ssn_dissector = get_itu_tcap_subdissector(ssn);
1207
1208                       if(tcap_ssn_dissector){
1209                           tcap_ssn_dissector_short_name = dissector_handle_get_short_name(tcap_ssn_dissector);
1210                           proto_item_append_text(item,", TCAP SSN linked to %s", tcap_ssn_dissector_short_name);
1211                       }
1212               }
1213           } /* short name */
1214       } /* ssn_dissector */
1215     } /* ssni */
1216
1217     if (!tree)
1218       return;   /* got SSN, that's all we need here... */
1219
1220     /* Dissect GT (if present) */
1221     if (gti != AI_GTI_NO_GT) {
1222       if (length < offset)
1223         return;
1224
1225       gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
1226                               (length - offset));
1227       dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
1228                                 called);
1229     }
1230
1231   } else if (decode_mtp3_standard == ANSI_STANDARD) {
1232
1233     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_global_title_indicator
1234                                              : hf_sccp_calling_ansi_global_title_indicator,
1235                         tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
1236
1237     pci = tvb_get_guint8(tvb, 0) & ANSI_PC_INDICATOR_MASK;
1238     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_point_code_indicator
1239                                              : hf_sccp_calling_ansi_point_code_indicator,
1240                         tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
1241
1242     ssni = tvb_get_guint8(tvb, 0) & ANSI_SSN_INDICATOR_MASK;
1243     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator
1244                                              : hf_sccp_calling_ansi_ssn_indicator,
1245                         tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
1246
1247     offset = ADDRESS_INDICATOR_LENGTH;
1248
1249     /* Dissect SSN (if present) */
1250     if (ssni) {
1251       ssn = tvb_get_guint8(tvb, offset);
1252
1253       if (called && assoc)
1254         assoc->called_ssn = ssn;
1255       else if (assoc)
1256         assoc->calling_ssn = ssn;
1257
1258       proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
1259                                             : hf_sccp_calling_ssn,
1260                           tvb, offset, ADDRESS_SSN_LENGTH, ssn);
1261       proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
1262                                  ADDRESS_SSN_LENGTH, ssn);
1263       offset += ADDRESS_SSN_LENGTH;
1264     }
1265
1266     if (!tree)
1267       return;   /* got SSN, that's all we need here... */
1268
1269     /* Dissect PC (if present) */
1270     if (pci) {
1271       offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
1272     }
1273
1274     /* Dissect GT (if present) */
1275     if (gti != AI_GTI_NO_GT) {
1276       if (length < offset)
1277         return;
1278       gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
1279                               (length - offset));
1280       dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
1281                                 called);
1282     }
1283
1284   }
1285
1286 }
1287
1288 static void
1289 dissect_sccp_called_param(tvbuff_t *tvb, proto_tree *tree, guint length)
1290 {
1291   dissect_sccp_called_calling_param(tvb, tree, length, TRUE);
1292 }
1293
1294 static void
1295 dissect_sccp_calling_param(tvbuff_t *tvb, proto_tree *tree, guint length)
1296 {
1297   dissect_sccp_called_calling_param(tvb, tree, length, FALSE);
1298 }
1299
1300 static void
1301 dissect_sccp_class_param(tvbuff_t *tvb, proto_tree *tree, guint length)
1302 {
1303   guint8 class, handling;
1304
1305   class = tvb_get_guint8(tvb, 0) & CLASS_CLASS_MASK;
1306   handling = tvb_get_guint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK;
1307
1308   proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, class);
1309
1310   if (class == 0 || class == 1)
1311     proto_tree_add_uint(tree, hf_sccp_handling, tvb, 0, length, handling);
1312 }
1313
1314 static void
1315 dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, proto_tree *tree, guint length)
1316 {
1317   proto_tree_add_item(tree, hf_sccp_more, tvb, 0, length, FALSE);
1318 }
1319
1320 static void
1321 dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, proto_tree *tree, guint length)
1322 {
1323   guint8 rsn;
1324
1325   rsn = tvb_get_guint8(tvb, 0) >> 1;
1326   proto_tree_add_uint(tree, hf_sccp_rsn, tvb, 0, length, rsn);
1327 }
1328
1329 static void
1330 dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, guint length)
1331 {
1332   guint8 rsn, ssn, more;
1333   proto_item *param_item;
1334   proto_tree *param_tree;
1335
1336   ssn = tvb_get_guint8(tvb, 0) >> 1;
1337   rsn = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) >> 1;
1338   more = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) & SEQUENCING_SEGMENTING_MORE_MASK;
1339
1340   param_item = proto_tree_add_text(tree, tvb, 0, length,
1341                                    val_to_str(PARAMETER_SEQUENCING_SEGMENTING,
1342                                               sccp_parameter_values, "Unknown"));
1343   param_tree = proto_item_add_subtree(param_item,
1344                                       ett_sccp_sequencing_segmenting);
1345
1346   proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_ssn, tvb, 0,
1347                       SEQUENCING_SEGMENTING_SSN_LENGTH, ssn);
1348   proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_rsn, tvb,
1349                       SEQUENCING_SEGMENTING_SSN_LENGTH,
1350                       SEQUENCING_SEGMENTING_RSN_LENGTH, rsn);
1351   proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_more, tvb,
1352                       SEQUENCING_SEGMENTING_SSN_LENGTH,
1353                       SEQUENCING_SEGMENTING_RSN_LENGTH, more);
1354 }
1355
1356 static void
1357 dissect_sccp_credit_param(tvbuff_t *tvb, proto_tree *tree, guint length)
1358 {
1359   guint8 credit;
1360
1361   credit = tvb_get_guint8(tvb, 0);
1362   proto_tree_add_uint(tree, hf_sccp_credit, tvb, 0, length, credit);
1363 }
1364
1365 static void
1366 dissect_sccp_release_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
1367 {
1368   guint8 cause;
1369
1370   cause = tvb_get_guint8(tvb, 0);
1371   proto_tree_add_uint(tree, hf_sccp_release_cause, tvb, 0, length, cause);
1372
1373   if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
1374     col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
1375 }
1376
1377 static void
1378 dissect_sccp_return_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
1379 {
1380   guint8 cause;
1381
1382   cause = tvb_get_guint8(tvb, 0);
1383   proto_tree_add_uint(tree, hf_sccp_return_cause, tvb, 0, length, cause);
1384
1385   if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
1386     col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
1387 }
1388
1389 static void
1390 dissect_sccp_reset_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
1391 {
1392   guint8 cause;
1393
1394   cause = tvb_get_guint8(tvb, 0);
1395   proto_tree_add_uint(tree, hf_sccp_reset_cause, tvb, 0, length, cause);
1396
1397   if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
1398     col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
1399 }
1400
1401 static void
1402 dissect_sccp_error_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
1403 {
1404   guint8 cause;
1405
1406   cause = tvb_get_guint8(tvb, 0);
1407   proto_tree_add_uint(tree, hf_sccp_error_cause, tvb, 0, length, cause);
1408
1409   if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
1410     col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
1411 }
1412
1413 static void
1414 dissect_sccp_refusal_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
1415 {
1416   guint8 cause;
1417
1418   cause = tvb_get_guint8(tvb, 0);
1419   proto_tree_add_uint(tree, hf_sccp_refusal_cause, tvb, 0, length, cause);
1420
1421   if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
1422     col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
1423 }
1424
1425 /* This function is used for both data and long data (ITU only) parameters */
1426 static void
1427 dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1428 {
1429     guint8 ssn = INVALID_SSN;
1430     guint8 other_ssn = INVALID_SSN;
1431         
1432         if (trace_sccp && assoc && assoc != &no_assoc) {
1433                 pinfo->sccp_info = assoc->curr_msg;
1434         } else {
1435                 pinfo->sccp_info = NULL;
1436         }
1437         
1438     if ( assoc ) {
1439                 other_ssn = INVALID_SSN;
1440
1441                 switch (pinfo->p2p_dir) {
1442                         case P2P_DIR_SENT:
1443                                 ssn = assoc->calling_ssn;
1444                                 break;
1445                         case P2P_DIR_RECV:
1446                                 ssn = assoc->called_ssn;
1447                                 break;
1448                         default:
1449                                 ssn = assoc->called_ssn;
1450                                 other_ssn = assoc->calling_ssn;
1451                                 break;
1452                 }
1453                 
1454     } else {
1455                 ssn = assoc->called_ssn;
1456                 other_ssn = assoc->calling_ssn;
1457     }
1458     
1459     if (ssn != INVALID_SSN && dissector_try_port(sccp_ssn_dissector_table, ssn, tvb, pinfo, tree)) {
1460                 return;
1461     }
1462
1463     if (other_ssn != INVALID_SSN && dissector_try_port(sccp_ssn_dissector_table, other_ssn, tvb, pinfo, tree)) {
1464                 return;
1465     }
1466
1467     /* try heuristic subdissector list to see if there are any takers */
1468     if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree)) {
1469                 return;
1470     }
1471
1472     /* No sub-dissection occured, treat it as raw data */
1473     call_dissector(data_handle, tvb, pinfo, tree);
1474
1475 }
1476
1477 static void
1478 dissect_sccp_segmentation_param(tvbuff_t *tvb, proto_tree *tree, guint length)
1479 {
1480   guint8 first, class, remaining;
1481   guint32 slr;
1482   proto_item *param_item;
1483   proto_tree *param_tree;
1484
1485   first = tvb_get_guint8(tvb, 0) & SEGMENTATION_FIRST_SEGMENT_MASK;
1486   class = tvb_get_guint8(tvb, 0) & SEGMENTATION_CLASS_MASK;
1487   remaining = tvb_get_guint8(tvb, 0) & SEGMENTATION_REMAINING_MASK;
1488
1489   slr = tvb_get_letoh24(tvb, 1);
1490
1491   param_item = proto_tree_add_text(tree, tvb, 0, length,
1492                                    val_to_str(PARAMETER_SEGMENTATION,
1493                                               sccp_parameter_values, "Unknown"));
1494   param_tree = proto_item_add_subtree(param_item, ett_sccp_segmentation);
1495
1496   proto_tree_add_uint(param_tree, hf_sccp_segmentation_first, tvb, 0, length,
1497                       first);
1498   proto_tree_add_uint(param_tree, hf_sccp_segmentation_class, tvb, 0, length,
1499                       class);
1500   proto_tree_add_uint(param_tree, hf_sccp_segmentation_remaining, tvb, 0,
1501                       length, remaining);
1502   proto_tree_add_uint(param_tree, hf_sccp_segmentation_slr, tvb, 1, length,
1503                       slr);
1504 }
1505
1506 static void
1507 dissect_sccp_hop_counter_param(tvbuff_t *tvb, proto_tree *tree, guint length)
1508 {
1509   guint8 hops;
1510
1511   hops = tvb_get_guint8(tvb, 0);
1512   proto_tree_add_uint(tree, hf_sccp_hop_counter, tvb, 0, length, hops);
1513 }
1514
1515 static void
1516 dissect_sccp_importance_param(tvbuff_t *tvb, proto_tree *tree, guint length)
1517 {
1518   guint8 importance;
1519
1520   importance = tvb_get_guint8(tvb, 0) & IMPORTANCE_IMPORTANCE_MASK;
1521   proto_tree_add_uint(tree, hf_sccp_importance, tvb, 0, length, importance);
1522 }
1523
1524 static void
1525 dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint length)
1526 {
1527   guint8 mi, iri, ti, network, netspec;
1528   guint offset = 0;
1529   proto_item *param_item;
1530   proto_tree *param_tree;
1531
1532   /* Create a subtree for ISNI Routing Control */
1533   param_item = proto_tree_add_text(tree, tvb, offset, ANSI_ISNI_ROUTING_CONTROL_LENGTH,
1534                                    "ISNI Routing Control");
1535   param_tree = proto_item_add_subtree(param_item,
1536                                       ett_sccp_ansi_isni_routing_control);
1537
1538   mi = tvb_get_guint8(tvb, offset) & ANSI_ISNI_MI_MASK;
1539   proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_mi, tvb, offset,
1540                       ANSI_ISNI_ROUTING_CONTROL_LENGTH, mi);
1541
1542   iri = tvb_get_guint8(tvb, offset) & ANSI_ISNI_IRI_MASK;
1543   proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_iri, tvb, offset,
1544                       ANSI_ISNI_ROUTING_CONTROL_LENGTH, iri);
1545
1546   ti = tvb_get_guint8(tvb, offset) & ANSI_ISNI_TI_MASK;
1547   proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_ti, tvb, offset,
1548                       ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
1549
1550   offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
1551
1552   if ((ti >> ANSI_ISNI_TI_SHIFT) == ANSI_ISNI_TYPE_1) {
1553     netspec = tvb_get_guint8(tvb, offset) & ANSI_ISNI_NETSPEC_MASK;
1554     proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_netspec, tvb, offset,
1555                         ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
1556     offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
1557   }
1558
1559   while (offset < length) {
1560
1561     network = tvb_get_guint8(tvb, offset);
1562     proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
1563                         "Network ID network: %d", network);
1564     offset++;
1565
1566     network = tvb_get_guint8(tvb, offset);
1567     proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
1568                         "Network ID cluster: %d", network);
1569     offset++;
1570   }
1571
1572 }
1573
1574 /*  FUNCTION dissect_sccp_parameter():
1575  *  Dissect a parameter given its type, offset into tvb, and length.
1576  */
1577 static guint16
1578 dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
1579                        proto_tree *tree, guint8 parameter_type, guint16 offset,
1580                        guint16 parameter_length)
1581 {
1582     tvbuff_t *parameter_tvb;
1583
1584     switch (parameter_type) {
1585     case PARAMETER_CALLED_PARTY_ADDRESS:
1586     case PARAMETER_CALLING_PARTY_ADDRESS:
1587     case PARAMETER_DATA:
1588     case PARAMETER_LONG_DATA:
1589     case PARAMETER_SOURCE_LOCAL_REFERENCE:
1590     case PARAMETER_DESTINATION_LOCAL_REFERENCE:
1591     case PARAMETER_RELEASE_CAUSE:
1592     case PARAMETER_RETURN_CAUSE:
1593     case PARAMETER_RESET_CAUSE:
1594     case PARAMETER_ERROR_CAUSE:
1595     case PARAMETER_REFUSAL_CAUSE:
1596
1597       /*  These parameters must be dissected even if !sccp_tree (so that
1598        *  assoc information can be created).
1599        */
1600       break;
1601
1602     default:
1603       if (!sccp_tree) return(parameter_length);
1604
1605     }
1606
1607     parameter_tvb = tvb_new_subset(tvb, offset, parameter_length, parameter_length);
1608
1609     switch (parameter_type) {
1610
1611     case PARAMETER_END_OF_OPTIONAL_PARAMETERS:
1612       proto_tree_add_text(sccp_tree, tvb, offset, parameter_length,
1613                           "End of Optional");
1614       break;
1615
1616     case PARAMETER_DESTINATION_LOCAL_REFERENCE:
1617       dissect_sccp_dlr_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
1618       break;
1619
1620     case PARAMETER_SOURCE_LOCAL_REFERENCE:
1621       dissect_sccp_slr_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
1622       break;
1623
1624     case PARAMETER_CALLED_PARTY_ADDRESS:
1625       dissect_sccp_called_param(parameter_tvb, sccp_tree, parameter_length);
1626       break;
1627
1628     case PARAMETER_CALLING_PARTY_ADDRESS:
1629       dissect_sccp_calling_param(parameter_tvb, sccp_tree, parameter_length);
1630       break;
1631
1632     case PARAMETER_CLASS:
1633       dissect_sccp_class_param(parameter_tvb, sccp_tree, parameter_length);
1634       break;
1635
1636     case PARAMETER_SEGMENTING_REASSEMBLING:
1637       dissect_sccp_segmenting_reassembling_param(parameter_tvb, sccp_tree,
1638                                                    parameter_length);
1639       break;
1640
1641     case PARAMETER_RECEIVE_SEQUENCE_NUMBER:
1642       dissect_sccp_receive_sequence_number_param(parameter_tvb, sccp_tree,
1643                                                  parameter_length);
1644       break;
1645
1646     case PARAMETER_SEQUENCING_SEGMENTING:
1647       dissect_sccp_sequencing_segmenting_param(parameter_tvb, sccp_tree,
1648                                                parameter_length);
1649       break;
1650
1651     case PARAMETER_CREDIT:
1652       dissect_sccp_credit_param(parameter_tvb, sccp_tree, parameter_length);
1653       break;
1654
1655     case PARAMETER_RELEASE_CAUSE:
1656       dissect_sccp_release_cause_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
1657       break;
1658
1659     case PARAMETER_RETURN_CAUSE:
1660       dissect_sccp_return_cause_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
1661       break;
1662
1663     case PARAMETER_RESET_CAUSE:
1664       dissect_sccp_reset_cause_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
1665       break;
1666
1667     case PARAMETER_ERROR_CAUSE:
1668       dissect_sccp_error_cause_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
1669       break;
1670
1671     case PARAMETER_REFUSAL_CAUSE:
1672       dissect_sccp_refusal_cause_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
1673       break;
1674
1675     case PARAMETER_DATA:
1676       dissect_sccp_data_param(parameter_tvb, pinfo, tree);
1677
1678       /* TODO? Re-adjust length of SCCP item since it may be sub-dissected */
1679       /* sccp_length = proto_item_get_len(sccp_item);
1680        * sccp_length -= parameter_length;
1681        * proto_item_set_len(sccp_item, sccp_length);
1682        */
1683       break;
1684
1685     case PARAMETER_SEGMENTATION:
1686       dissect_sccp_segmentation_param(parameter_tvb, sccp_tree, parameter_length);
1687       break;
1688
1689     case PARAMETER_HOP_COUNTER:
1690       dissect_sccp_hop_counter_param(parameter_tvb, sccp_tree, parameter_length);
1691       break;
1692
1693     case PARAMETER_IMPORTANCE:
1694       if (decode_mtp3_standard != ANSI_STANDARD)
1695         dissect_sccp_importance_param(parameter_tvb, sccp_tree, parameter_length);
1696       else
1697         dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1698                                    parameter_length);
1699       break;
1700
1701     case PARAMETER_LONG_DATA:
1702       if (decode_mtp3_standard != ANSI_STANDARD)
1703         dissect_sccp_data_param(parameter_tvb, pinfo, tree);
1704       else
1705         dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1706                                    parameter_length);
1707       break;
1708
1709     case PARAMETER_ISNI:
1710       if (decode_mtp3_standard != ANSI_STANDARD)
1711         dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1712                                    parameter_length);
1713       else
1714         dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
1715       break;
1716
1717     default:
1718       dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1719                                  parameter_length);
1720       break;
1721     }
1722
1723     return(parameter_length);
1724 }
1725
1726 /*  FUNCTION dissect_sccp_variable_parameter():
1727  *  Dissect a variable parameter given its type and offset into tvb.  Length
1728  *  of the parameter is gotten from tvb[0].
1729  *  Length returned is sum of (length + parameter).
1730  */
1731 static guint16
1732 dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo,
1733                                 proto_tree *sccp_tree, proto_tree *tree,
1734                                 guint8 parameter_type, guint16 offset)
1735 {
1736   guint16 parameter_length;
1737   guint8 length_length;
1738
1739   if (parameter_type != PARAMETER_LONG_DATA)
1740   {
1741     parameter_length = tvb_get_guint8(tvb, offset);
1742     length_length = PARAMETER_LENGTH_LENGTH;
1743   }
1744   else
1745   {
1746     /* Long data parameter has 16 bit length */
1747     parameter_length = tvb_get_letohs(tvb, offset);
1748     length_length = PARAMETER_LONG_DATA_LENGTH_LENGTH;
1749   }
1750
1751   if (sccp_tree && sccp_show_length)
1752   {
1753     proto_tree_add_text(sccp_tree, tvb, offset, length_length,
1754                         "%s length: %d",
1755                         val_to_str(parameter_type, sccp_parameter_values,
1756                                    "Unknown"),
1757                         parameter_length);
1758   }
1759
1760   offset += length_length;
1761
1762   dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
1763                          parameter_length);
1764
1765   return(parameter_length + length_length);
1766 }
1767
1768 /*  FUNCTION dissect_sccp_optional_parameters():
1769  *  Dissect all the optional parameters given the start of the optional
1770  *  parameters into tvb.  Parameter types and lengths are read from tvb.
1771  */
1772 static void
1773 dissect_sccp_optional_parameters(tvbuff_t *tvb, packet_info *pinfo,
1774                                  proto_tree *sccp_tree, proto_tree *tree,
1775                                  guint16 offset)
1776 {
1777   guint8 parameter_type;
1778
1779   while ((parameter_type = tvb_get_guint8(tvb, offset)) !=
1780          PARAMETER_END_OF_OPTIONAL_PARAMETERS) {
1781
1782     offset += PARAMETER_TYPE_LENGTH;
1783     offset += dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1784                                               parameter_type, offset);
1785   }
1786
1787   /* Process end of optional parameters */
1788   dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
1789                          END_OF_OPTIONAL_PARAMETERS_LENGTH);
1790
1791 }
1792
1793
1794 static void
1795 dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
1796                      proto_tree *tree)
1797 {
1798   guint16 variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
1799   guint16 optional_pointer = 0, orig_opt_ptr = 0;
1800   guint16 offset = 0;
1801   guint8 parameter_type;
1802   gboolean   save_fragmented;
1803   tvbuff_t *new_tvb = NULL;
1804   fragment_data *frag_msg = NULL;
1805   guint32 source_local_ref=0;
1806   guint8 more;
1807   guint msg_offset = offset_from_real_beginning(tvb,0);
1808         
1809 /* Macro for getting pointer to mandatory variable parameters */
1810 #define VARIABLE_POINTER(var, hf_var, ptr_size) \
1811     if (ptr_size == POINTER_LENGTH) \
1812         var = tvb_get_guint8(tvb, offset); \
1813     else \
1814         var = tvb_get_letohs(tvb, offset); \
1815     proto_tree_add_uint(sccp_tree, hf_var, tvb, \
1816                         offset, ptr_size, var); \
1817     var += offset; \
1818     if (ptr_size == POINTER_LENGTH_LONG) \
1819         var += 1; \
1820     offset += ptr_size;
1821
1822 /* Macro for getting pointer to optional parameters */
1823 #define OPTIONAL_POINTER(ptr_size) \
1824     if (ptr_size == POINTER_LENGTH) \
1825         orig_opt_ptr = optional_pointer = tvb_get_guint8(tvb, offset); \
1826     else \
1827         orig_opt_ptr = optional_pointer = tvb_get_letohs(tvb, offset); \
1828     proto_tree_add_uint(sccp_tree, hf_sccp_optional_pointer, tvb, \
1829                         offset, ptr_size, optional_pointer); \
1830     optional_pointer += offset; \
1831     if (ptr_size == POINTER_LENGTH_LONG) \
1832         optional_pointer += 1; \
1833     offset += ptr_size;
1834
1835
1836   /* Extract the message type;  all other processing is based on this */
1837   message_type   = tvb_get_guint8(tvb, SCCP_MSG_TYPE_OFFSET);
1838   offset = SCCP_MSG_TYPE_LENGTH;
1839
1840   if (check_col(pinfo->cinfo, COL_INFO)) {
1841     col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
1842                  val_to_str(message_type, sccp_message_type_acro_values, "Unknown"));
1843   };
1844
1845   if (sccp_tree) {
1846     /* add the message type to the protocol tree */
1847     proto_tree_add_uint(sccp_tree, hf_sccp_message_type, tvb,
1848                         SCCP_MSG_TYPE_OFFSET, SCCP_MSG_TYPE_LENGTH, message_type);
1849
1850   };
1851
1852   /* Starting a new message dissection; clear the global assoc, SLR, and DLR values */
1853   dlr = 0;
1854   slr = 0;
1855   assoc = NULL;
1856   
1857   no_assoc.calling_dpc = 0;
1858   no_assoc.called_dpc = 0;
1859   no_assoc.calling_ssn = INVALID_SSN;
1860   no_assoc.called_ssn = INVALID_SSN;
1861   no_assoc.has_fw_key = FALSE;
1862   no_assoc.has_bw_key = FALSE;
1863   no_assoc.payload = SCCP_PLOAD_NONE;
1864   no_assoc.called_party = NULL;
1865   no_assoc.calling_party = NULL;
1866   no_assoc.extra_info = NULL;
1867
1868   switch(message_type) {
1869   case SCCP_MSG_TYPE_CR:
1870   /*  TTC and NTT (Japan) say that the connection-oriented messages are
1871    *  deleted (not standardized), but they appear to be used anyway, so
1872    *  we'll dissect it...
1873    */
1874     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1875                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1876                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1877     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1878                                      PARAMETER_CLASS, offset,
1879                                      PROTOCOL_CLASS_LENGTH);
1880       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
1881
1882     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1883     OPTIONAL_POINTER(POINTER_LENGTH)
1884
1885     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1886                                     PARAMETER_CALLED_PARTY_ADDRESS,
1887                                     variable_pointer1);
1888     break;
1889
1890   case SCCP_MSG_TYPE_CC:
1891     /*  TODO: connection has been established;  theoretically we could keep
1892      *  keep track of the SLR/DLR with the called/calling from the CR and
1893      *  track the connection (e.g., on subsequent messages regarding this
1894      *  SLR we could set the global vars "call*_ssn" so data could get
1895      *  sub-dissected).
1896      */
1897     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1898                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1899                                      offset,
1900                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1901     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1902                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1903                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1904
1905       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
1906
1907     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1908                                      PARAMETER_CLASS, offset,
1909                                      PROTOCOL_CLASS_LENGTH);
1910     OPTIONAL_POINTER(POINTER_LENGTH);
1911     break;
1912
1913   case SCCP_MSG_TYPE_CREF:
1914     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1915                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1916                                      offset,
1917                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1918
1919       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
1920
1921     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1922                                      PARAMETER_REFUSAL_CAUSE, offset,
1923                                      REFUSAL_CAUSE_LENGTH);
1924     OPTIONAL_POINTER(POINTER_LENGTH);
1925     break;
1926
1927   case SCCP_MSG_TYPE_RLSD:
1928     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1929                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1930                                      offset,
1931                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1932     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1933                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1934                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1935
1936       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
1937
1938     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1939                                      PARAMETER_RELEASE_CAUSE, offset,
1940                                      RELEASE_CAUSE_LENGTH);
1941
1942     OPTIONAL_POINTER(POINTER_LENGTH);
1943       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
1944     break;
1945
1946   case SCCP_MSG_TYPE_RLC:
1947     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1948                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1949                                      offset,
1950                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1951     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1952                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1953                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1954
1955       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
1956
1957     break;
1958
1959   case SCCP_MSG_TYPE_DT1:
1960     source_local_ref = tvb_get_letoh24(tvb, offset);
1961     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1962                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1963                                      offset,
1964                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1965
1966       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
1967
1968     more = tvb_get_guint8(tvb, offset) & SEGMENTING_REASSEMBLING_MASK;
1969
1970     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1971                                      PARAMETER_SEGMENTING_REASSEMBLING,
1972                                      offset, SEGMENTING_REASSEMBLING_LENGTH);
1973     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1974
1975     /* Reasemble */
1976     if (!sccp_xudt_desegment) {
1977         proto_tree_add_text(sccp_tree, tvb, variable_pointer1,
1978                             tvb_get_guint8(tvb, variable_pointer1)+1,
1979                             "Segmented Data");
1980         dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1981                                         PARAMETER_DATA, variable_pointer1);
1982
1983     } else {
1984         save_fragmented = pinfo->fragmented;
1985         pinfo->fragmented = TRUE;
1986         frag_msg = fragment_add_seq_next(tvb, variable_pointer1 + 1, pinfo,
1987                              source_local_ref,                  /* ID for fragments belonging together */
1988                              sccp_xudt_msg_fragment_table,      /* list of message fragments */
1989                              sccp_xudt_msg_reassembled_table,   /* list of reassembled messages */
1990                              tvb_get_guint8(tvb,variable_pointer1),/* fragment length - to the end */
1991                              more);                             /* More fragments? */
1992
1993         new_tvb = process_reassembled_data(tvb, variable_pointer1 + 1, pinfo,
1994                                            "Reassembled Message", frag_msg,
1995                                            &sccp_xudt_msg_frag_items, NULL,
1996                                            tree);
1997
1998         if (frag_msg && frag_msg->next) { /* Reassembled */
1999             if (check_col(pinfo->cinfo, COL_INFO))
2000                 col_append_str(pinfo->cinfo, COL_INFO,
2001                                "(Message reassembled) ");
2002         } else if (more) { /* Not last packet of reassembled message */
2003             if (check_col(pinfo->cinfo, COL_INFO))
2004                 col_append_str(pinfo->cinfo, COL_INFO, "(Message fragment) ");
2005         }
2006
2007         pinfo->fragmented = save_fragmented;
2008
2009         if (new_tvb)
2010             dissect_sccp_data_param(new_tvb, pinfo, tree);
2011     }
2012
2013     /* End reassemble */
2014     break;
2015
2016   case SCCP_MSG_TYPE_DT2:
2017     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2018                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
2019                                      offset,
2020                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
2021
2022       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2023
2024     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2025                                      PARAMETER_SEQUENCING_SEGMENTING, offset,
2026                                      SEQUENCING_SEGMENTING_LENGTH);
2027     break;
2028
2029   case SCCP_MSG_TYPE_AK:
2030     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2031                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
2032                                      offset,
2033                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
2034
2035       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2036
2037     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2038                                      PARAMETER_RECEIVE_SEQUENCE_NUMBER,
2039                                      offset, RECEIVE_SEQUENCE_NUMBER_LENGTH);
2040     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2041                                      PARAMETER_CREDIT, offset, CREDIT_LENGTH);
2042     break;
2043
2044   case SCCP_MSG_TYPE_UDT:
2045     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2046                                      PARAMETER_CLASS, offset,
2047                                      PROTOCOL_CLASS_LENGTH);
2048     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
2049     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
2050     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
2051
2052       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2053
2054     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2055                                     PARAMETER_CALLED_PARTY_ADDRESS,
2056                                     variable_pointer1);
2057     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2058                                     PARAMETER_CALLING_PARTY_ADDRESS,
2059                                     variable_pointer2);
2060
2061     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
2062                                     variable_pointer3);
2063     break;
2064
2065   case SCCP_MSG_TYPE_UDTS:
2066     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2067                                      PARAMETER_RETURN_CAUSE, offset,
2068                                      RETURN_CAUSE_LENGTH);
2069
2070     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
2071     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
2072     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
2073
2074     assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2075
2076     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2077                                     PARAMETER_CALLED_PARTY_ADDRESS,
2078                                     variable_pointer1);
2079
2080     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2081                                     PARAMETER_CALLING_PARTY_ADDRESS,
2082                                     variable_pointer2);
2083
2084     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
2085                                     variable_pointer3);
2086     break;
2087
2088   case SCCP_MSG_TYPE_ED:
2089     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2090                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
2091                                      offset,
2092                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
2093
2094       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2095
2096     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH);
2097
2098     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
2099                                     variable_pointer1);
2100     break;
2101
2102   case SCCP_MSG_TYPE_EA:
2103     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2104                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
2105                                      offset,
2106                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
2107       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2108
2109     break;
2110
2111   case SCCP_MSG_TYPE_RSR:
2112     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2113                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
2114                                      offset,
2115                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
2116     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2117                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
2118                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
2119     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2120                                      PARAMETER_RESET_CAUSE, offset,
2121                                      RESET_CAUSE_LENGTH);
2122       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2123     break;
2124
2125   case SCCP_MSG_TYPE_RSC:
2126     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2127                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
2128                                      offset,
2129                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
2130     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2131                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
2132                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
2133       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2134     break;
2135
2136   case SCCP_MSG_TYPE_ERR:
2137     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2138                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
2139                                      offset,
2140                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
2141     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2142                                      PARAMETER_ERROR_CAUSE, offset,
2143                                      ERROR_CAUSE_LENGTH);
2144       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2145     break;
2146
2147   case SCCP_MSG_TYPE_IT:
2148     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2149                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
2150                                      offset,
2151                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
2152     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2153                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
2154                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
2155       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2156     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2157                                      PARAMETER_CLASS, offset,
2158                                      PROTOCOL_CLASS_LENGTH);
2159     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2160                                      PARAMETER_SEQUENCING_SEGMENTING,
2161                                      offset, SEQUENCING_SEGMENTING_LENGTH);
2162     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2163                                      PARAMETER_CREDIT, offset, CREDIT_LENGTH);
2164     break;
2165
2166   case SCCP_MSG_TYPE_XUDT:
2167     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2168                                      PARAMETER_CLASS, offset,
2169                                      PROTOCOL_CLASS_LENGTH);
2170     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2171                                      PARAMETER_HOP_COUNTER, offset,
2172                                      HOP_COUNTER_LENGTH);
2173
2174     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
2175     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
2176     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
2177     OPTIONAL_POINTER(POINTER_LENGTH)
2178
2179     /*  Optional parameters are Segmentation and Importance
2180      *  NOTE 2 - Segmentation Should not be present in case of a single XUDT
2181      *  message.
2182      */
2183
2184       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2185
2186     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2187                                     PARAMETER_CALLED_PARTY_ADDRESS,
2188                                     variable_pointer1);
2189     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2190                                     PARAMETER_CALLING_PARTY_ADDRESS,
2191                                     variable_pointer2);
2192
2193     if ((parameter_type = tvb_get_guint8(tvb, optional_pointer)) == PARAMETER_SEGMENTATION){
2194         if (!sccp_xudt_desegment){
2195             proto_tree_add_text(sccp_tree, tvb, variable_pointer3, tvb_get_guint8(tvb, variable_pointer3)+1, "Segmented Data"  );
2196
2197         } else {
2198             guint8 octet;
2199             gboolean more_frag = TRUE;
2200
2201
2202             /* Get the first octet of parameter Segmentation, Ch 3.17 in Q.713
2203              * Bit 8 of octet 1 is used for First segment indication
2204              * Bit 7 of octet 1 is used to keep in the message in sequence
2205              *       delivery option required by the SCCP user
2206              * Bits 6 and 5 in octet 1 are spare bits.
2207              * Bits 4-1 of octet 1 are used to indicate the number of
2208              *          remaining segments.
2209              * The values 0000 to 1111 are possible; the value 0000 indicates
2210              * the last segment.
2211              */
2212             octet = tvb_get_guint8(tvb,optional_pointer+2);
2213             source_local_ref = tvb_get_letoh24(tvb, optional_pointer+3);
2214
2215             if ((octet&0x0f) == 0)
2216                 more_frag = FALSE;
2217
2218             save_fragmented = pinfo->fragmented;
2219             pinfo->fragmented = TRUE;
2220             frag_msg = fragment_add_seq_next(tvb, variable_pointer3 + 1, pinfo,
2221                     source_local_ref,                           /* ID for fragments belonging together */
2222                     sccp_xudt_msg_fragment_table,               /* list of message fragments */
2223                     sccp_xudt_msg_reassembled_table,            /* list of reassembled messages */
2224                     tvb_get_guint8(tvb,variable_pointer3),      /* fragment length - to the end */
2225                     more_frag);                                 /* More fragments? */
2226
2227             if ((octet&0x80) == 0x80) /*First segment, set number of segments*/
2228                 fragment_set_tot_len(pinfo, source_local_ref, sccp_xudt_msg_fragment_table,(octet & 0xf));
2229
2230             new_tvb = process_reassembled_data(tvb, variable_pointer3 + 1,
2231                                                pinfo, "Reassembled Message",
2232                                                frag_msg,
2233                                                &sccp_xudt_msg_frag_items,
2234                                                NULL, tree);
2235
2236             if (frag_msg) { /* Reassembled */
2237                 if (check_col(pinfo->cinfo, COL_INFO))
2238                     col_append_str(pinfo->cinfo, COL_INFO,
2239                                    "(Message reassembled) ");
2240             } else { /* Not last packet of reassembled message */
2241                 if (check_col(pinfo->cinfo, COL_INFO))
2242                     col_append_str(pinfo->cinfo, COL_INFO,
2243                                     "(Message fragment) ");
2244             }
2245
2246             pinfo->fragmented = save_fragmented;
2247
2248             if (new_tvb)
2249                 dissect_sccp_data_param(new_tvb, pinfo, tree);
2250         }
2251     } else {
2252         dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2253                                         PARAMETER_DATA, variable_pointer3);
2254     }
2255     break;
2256
2257   case SCCP_MSG_TYPE_XUDTS:
2258     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2259                                      PARAMETER_RETURN_CAUSE, offset,
2260                                      RETURN_CAUSE_LENGTH);
2261     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2262                                      PARAMETER_HOP_COUNTER, offset,
2263                                      HOP_COUNTER_LENGTH);
2264
2265     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
2266     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
2267     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
2268     OPTIONAL_POINTER(POINTER_LENGTH)
2269
2270       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2271
2272     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2273                                     PARAMETER_CALLED_PARTY_ADDRESS,
2274                                     variable_pointer1);
2275     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2276                                     PARAMETER_CALLING_PARTY_ADDRESS,
2277                                     variable_pointer2);
2278     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
2279                                     variable_pointer3);
2280     break;
2281
2282   case SCCP_MSG_TYPE_LUDT:
2283     if (decode_mtp3_standard != ANSI_STANDARD)
2284     {
2285       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2286                                        PARAMETER_CLASS, offset,
2287                                        PROTOCOL_CLASS_LENGTH);
2288       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2289                                        PARAMETER_HOP_COUNTER, offset,
2290                                        HOP_COUNTER_LENGTH);
2291
2292       VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
2293       VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
2294       VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
2295       OPTIONAL_POINTER(POINTER_LENGTH_LONG)
2296
2297       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2298
2299       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2300                                       PARAMETER_CALLED_PARTY_ADDRESS,
2301                                       variable_pointer1);
2302       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2303                                       PARAMETER_CALLING_PARTY_ADDRESS,
2304                                       variable_pointer2);
2305       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2306                                       PARAMETER_LONG_DATA, variable_pointer3);
2307     } else
2308       dissect_sccp_unknown_message(tvb, sccp_tree);
2309     break;
2310
2311   case SCCP_MSG_TYPE_LUDTS:
2312     if (decode_mtp3_standard != ANSI_STANDARD)
2313     {
2314       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2315                                        PARAMETER_RETURN_CAUSE, offset,
2316                                        RETURN_CAUSE_LENGTH);
2317       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
2318                                        PARAMETER_HOP_COUNTER, offset,
2319                                        HOP_COUNTER_LENGTH);
2320
2321       VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
2322       VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
2323       VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
2324       OPTIONAL_POINTER(POINTER_LENGTH_LONG)
2325
2326       assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
2327
2328       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2329                                       PARAMETER_CALLED_PARTY_ADDRESS,
2330                                       variable_pointer1);
2331       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2332                                       PARAMETER_CALLING_PARTY_ADDRESS,
2333                                       variable_pointer2);
2334       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2335                                       PARAMETER_LONG_DATA, variable_pointer3);
2336     } else
2337       dissect_sccp_unknown_message(tvb, sccp_tree);
2338     break;
2339
2340   default:
2341     dissect_sccp_unknown_message(tvb, sccp_tree);
2342   }
2343
2344   if (orig_opt_ptr)
2345     dissect_sccp_optional_parameters(tvb, pinfo, sccp_tree, tree,
2346                                      optional_pointer);
2347   
2348   if (trace_sccp && assoc && assoc != &no_assoc) {
2349           proto_item* pi = proto_tree_add_uint(sccp_tree,hf_sccp_assoc_id,tvb,0,0,assoc->id);
2350           proto_tree* pt = proto_item_add_subtree(pi,ett_sccp_assoc);
2351           PROTO_ITEM_SET_GENERATED(pi);
2352           if (assoc->msgs) {
2353                 sccp_msg_info_t* m;
2354                   for(m = assoc->msgs; m ; m = m->next) {       
2355                         pi = proto_tree_add_uint( pt,hf_sccp_assoc_msg,tvb,0,0,m->framenum);
2356                         
2357                         if (assoc->payload != SCCP_PLOAD_NONE) 
2358                                 proto_item_append_text(pi," %s", val_to_str(assoc->payload, assoc_protos, "Unknown"));
2359                         
2360                         if (m->label)
2361                                 proto_item_append_text(pi," %s", m->label);
2362                         
2363                         if (m->framenum == pinfo->fd->num && m->offset == msg_offset ) {
2364                                 tap_queue_packet(sccp_tap, pinfo, m);
2365                                 proto_item_append_text(pi," (current)");
2366                         }
2367                         PROTO_ITEM_SET_GENERATED(pi);
2368                   }
2369           }
2370   }
2371
2372 }
2373
2374 static void
2375 dissect_sccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2376 {
2377   proto_item *sccp_item = NULL;
2378   proto_tree *sccp_tree = NULL;
2379   const mtp3_addr_pc_t *mtp3_addr_p;
2380
2381   if ((pinfo->src.type == AT_SS7PC) &&
2382     ((mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data)->type <= CHINESE_ITU_STANDARD))
2383   {
2384     /*
2385      *  Allow a protocol beneath to specify how the SCCP layer should be
2386      *  dissected.
2387      *
2388      *  It is possible to have multiple sets of SCCP traffic some of which is
2389      *  ITU and some of which is ANSI.
2390      *  An example is A-interface traffic having ANSI MTP3/ANSI SCCP/3GPP2 IOS
2391      *  and at the same time ITU MTP3/ITU SCCP/ANSI TCAP/ANSI MAP.
2392      */
2393     decode_mtp3_standard = mtp3_addr_p->type;
2394   }
2395   else
2396   {
2397     decode_mtp3_standard = mtp3_standard;
2398   }
2399
2400   /* Make entry in the Protocol column on summary display */
2401   if (check_col(pinfo->cinfo, COL_PROTOCOL))
2402     switch(decode_mtp3_standard) {
2403       case ITU_STANDARD:
2404         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Int. ITU)");
2405         break;
2406       case ANSI_STANDARD:
2407         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (ANSI)");
2408         break;
2409       case CHINESE_ITU_STANDARD:
2410         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Chin. ITU)");
2411         break;
2412       case JAPAN_STANDARD:
2413         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Japan)");
2414         break;
2415     };
2416
2417   /* In the interest of speed, if "tree" is NULL, don't do any work not
2418      necessary to generate protocol tree items. */
2419   if (tree) {
2420     /* create the sccp protocol tree */
2421     sccp_item = proto_tree_add_item(tree, proto_sccp, tvb, 0, -1, FALSE);
2422     sccp_tree = proto_item_add_subtree(sccp_item, ett_sccp);
2423   }
2424
2425   /* Set whether message is UPLINK, DOWNLINK, or of UNKNOWN direction */
2426
2427   if (pinfo->src.type == AT_SS7PC)
2428   {
2429     /*
2430      * XXX - we assume that the "data" pointers of the source and destination
2431      * addresses are set to point to "mtp3_addr_pc_t" structures, so that
2432      * we can safely cast them.
2433      */
2434     mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data;
2435
2436     if (sccp_source_pc_global == mtp3_addr_p->pc)
2437     {
2438        pinfo->p2p_dir = P2P_DIR_SENT;
2439     }
2440     else
2441     {
2442       /* assuming if src was SS7 PC then dst will be too */
2443       mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->dst.data;
2444
2445       if (sccp_source_pc_global == mtp3_addr_p->pc)
2446       {
2447          pinfo->p2p_dir = P2P_DIR_RECV;
2448       }
2449       else
2450       {
2451          pinfo->p2p_dir = P2P_DIR_UNKNOWN;
2452       }
2453     }
2454   }
2455
2456   /* dissect the message */
2457   dissect_sccp_message(tvb, pinfo, sccp_tree, tree);
2458   
2459 }
2460
2461 static void init_sccp(void) {
2462     next_assoc_id = 1;
2463     fragment_table_init (&sccp_xudt_msg_fragment_table);
2464     reassembled_table_init(&sccp_xudt_msg_reassembled_table);
2465
2466 }
2467
2468 /* Register the protocol with Wireshark */
2469 void
2470 proto_register_sccp(void)
2471 {
2472   /* Setup list of header fields */
2473   static hf_register_info hf[] = {
2474     { &hf_sccp_message_type,
2475       { "Message Type", "sccp.message_type",
2476         FT_UINT8, BASE_HEX, VALS(sccp_message_type_values), 0x0,
2477         "", HFILL}},
2478     { &hf_sccp_variable_pointer1,
2479       { "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1",
2480         FT_UINT16, BASE_DEC, NULL, 0x0,
2481         "", HFILL}},
2482     { &hf_sccp_variable_pointer2,
2483       { "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2",
2484         FT_UINT16, BASE_DEC, NULL, 0x0,
2485         "", HFILL}},
2486     { &hf_sccp_variable_pointer3,
2487       { "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3",
2488         FT_UINT16, BASE_DEC, NULL, 0x0,
2489         "", HFILL}},
2490     { &hf_sccp_optional_pointer,
2491       { "Pointer to Optional parameter", "sccp.optional_pointer",
2492         FT_UINT16, BASE_DEC, NULL, 0x0,
2493         "", HFILL}},
2494     { &hf_sccp_ssn,
2495       { "Called or Calling SubSystem Number", "sccp.ssn",
2496         FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
2497         "", HFILL}},
2498     { &hf_sccp_gt_digits,
2499       { "Called or Calling GT Digits",
2500         "sccp.digits",
2501         FT_STRING, BASE_NONE, NULL, 0x0,
2502         "", HFILL }},
2503     { &hf_sccp_called_national_indicator,
2504       { "National Indicator", "sccp.called.ni",
2505         FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
2506         "", HFILL}},
2507     { &hf_sccp_called_routing_indicator,
2508       { "Routing Indicator", "sccp.called.ri",
2509         FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
2510         "", HFILL}},
2511     { &hf_sccp_called_itu_global_title_indicator,
2512       { "Global Title Indicator", "sccp.called.gti",
2513         FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
2514         "", HFILL}},
2515     { &hf_sccp_called_ansi_global_title_indicator,
2516       { "Global Title Indicator", "sccp.called.gti",
2517         FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
2518         "", HFILL}},
2519     { &hf_sccp_called_itu_ssn_indicator,
2520       { "SubSystem Number Indicator", "sccp.called.ssni",
2521         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
2522         "", HFILL}},
2523     { &hf_sccp_called_itu_point_code_indicator,
2524       { "Point Code Indicator", "sccp.called.pci",
2525         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
2526         "", HFILL}},
2527     { &hf_sccp_called_ansi_ssn_indicator,
2528       { "SubSystem Number Indicator", "sccp.called.ssni",
2529         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
2530         "", HFILL}},
2531     { &hf_sccp_called_ansi_point_code_indicator,
2532       { "Point Code Indicator", "sccp.called.pci",
2533         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
2534         "", HFILL}},
2535     { &hf_sccp_called_ssn,
2536       { "SubSystem Number", "sccp.called.ssn",
2537         FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
2538         "", HFILL}},
2539     { &hf_sccp_called_itu_pc,
2540       { "PC", "sccp.called.pc",
2541         FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
2542         "", HFILL}},
2543     { &hf_sccp_called_ansi_pc,
2544       { "PC", "sccp.called.ansi_pc",
2545         FT_STRING, BASE_NONE, NULL, 0x0,
2546         "", HFILL}},
2547     { &hf_sccp_called_chinese_pc,
2548       { "PC", "sccp.called.chinese_pc",
2549         FT_STRING, BASE_NONE, NULL, 0x0,
2550         "", HFILL}},
2551     { &hf_sccp_called_japan_pc,
2552       { "PC", "sccp.called.pc",
2553         FT_UINT16, BASE_DEC, NULL, 0x0,
2554         "", HFILL}},
2555     { &hf_sccp_called_pc_network,
2556       { "PC Network",
2557         "sccp.called.network",
2558         FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
2559         "", HFILL }},
2560     { &hf_sccp_called_pc_cluster,
2561       { "PC Cluster",
2562         "sccp.called.cluster",
2563         FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
2564         "", HFILL }},
2565     { &hf_sccp_called_pc_member,
2566       { "PC Member",
2567         "sccp.called.member",
2568         FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
2569         "", HFILL }},
2570     { &hf_sccp_called_gt_nai,
2571       { "Nature of Address Indicator",
2572         "sccp.called.nai",
2573         FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
2574         "", HFILL }},
2575     { &hf_sccp_called_gt_oe,
2576       { "Odd/Even Indicator",
2577         "sccp.called.oe",
2578         FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
2579         "", HFILL }},
2580     { &hf_sccp_called_gt_tt,
2581       { "Translation Type",
2582         "sccp.called.tt",
2583         FT_UINT8, BASE_HEX, NULL, 0x0,
2584         "", HFILL }},
2585     { &hf_sccp_called_gt_np,
2586       { "Numbering Plan",
2587         "sccp.called.np",
2588         FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
2589         "", HFILL }},
2590     { &hf_sccp_called_gt_es,
2591       { "Encoding Scheme",
2592         "sccp.called.es",
2593         FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
2594         "", HFILL }},
2595     { &hf_sccp_called_gt_digits,
2596       { "GT Digits",
2597         "sccp.called.digits",
2598         FT_STRING, BASE_NONE, NULL, 0x0,
2599         "", HFILL }},
2600     { &hf_sccp_calling_national_indicator,
2601       { "National Indicator", "sccp.calling.ni",
2602         FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
2603         "", HFILL}},
2604     { &hf_sccp_calling_routing_indicator,
2605       { "Routing Indicator", "sccp.calling.ri",
2606         FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
2607         "", HFILL}},
2608     { &hf_sccp_calling_itu_global_title_indicator,
2609       { "Global Title Indicator", "sccp.calling.gti",
2610         FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
2611         "", HFILL}},
2612     { &hf_sccp_calling_ansi_global_title_indicator,
2613       { "Global Title Indicator", "sccp.calling.gti",
2614         FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
2615         "", HFILL}},
2616     { &hf_sccp_calling_itu_ssn_indicator,
2617       { "SubSystem Number Indicator", "sccp.calling.ssni",
2618         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
2619         "", HFILL}},
2620     { &hf_sccp_calling_itu_point_code_indicator,
2621       { "Point Code Indicator", "sccp.calling.pci",
2622         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
2623         "", HFILL}},
2624     { &hf_sccp_calling_ansi_ssn_indicator,
2625       { "SubSystem Number Indicator", "sccp.calling.ssni",
2626         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
2627         "", HFILL}},
2628     { &hf_sccp_calling_ansi_point_code_indicator,
2629       { "Point Code Indicator", "sccp.calling.pci",
2630         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
2631         "", HFILL}},
2632     { &hf_sccp_calling_ssn,
2633       { "SubSystem Number", "sccp.calling.ssn",
2634         FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
2635         "", HFILL}},
2636     { &hf_sccp_calling_itu_pc,
2637       { "PC", "sccp.calling.pc",
2638         FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
2639         "", HFILL}},
2640     { &hf_sccp_calling_ansi_pc,
2641       { "PC", "sccp.calling.ansi_pc",
2642         FT_STRING, BASE_NONE, NULL, 0x0,
2643         "", HFILL}},
2644     { &hf_sccp_calling_chinese_pc,
2645       { "PC", "sccp.calling.chinese_pc",
2646         FT_STRING, BASE_NONE, NULL, 0x0,
2647         "", HFILL}},
2648     { &hf_sccp_calling_japan_pc,
2649       { "PC", "sccp.calling.pc",
2650         FT_UINT16, BASE_DEC, NULL, 0x0,
2651         "", HFILL}},
2652     { &hf_sccp_calling_pc_network,
2653       { "PC Network",
2654         "sccp.calling.network",
2655         FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
2656         "", HFILL }},
2657     { &hf_sccp_calling_pc_cluster,
2658       { "PC Cluster",
2659         "sccp.calling.cluster",
2660         FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
2661         "", HFILL }},
2662     { &hf_sccp_calling_pc_member,
2663       { "PC Member",
2664         "sccp.calling.member",
2665         FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
2666         "", HFILL }},
2667     { &hf_sccp_calling_gt_nai,
2668       { "Nature of Address Indicator",
2669         "sccp.calling.nai",
2670         FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
2671         "", HFILL }},
2672     { &hf_sccp_calling_gt_oe,
2673       { "Odd/Even Indicator",
2674         "sccp.calling.oe",
2675         FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
2676         "", HFILL }},
2677     { &hf_sccp_calling_gt_tt,
2678       { "Translation Type",
2679         "sccp.calling.tt",
2680         FT_UINT8, BASE_HEX, NULL, 0x0,
2681         "", HFILL }},
2682     { &hf_sccp_calling_gt_np,
2683       { "Numbering Plan",
2684         "sccp.calling.np",
2685         FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
2686         "", HFILL }},
2687     { &hf_sccp_calling_gt_es,
2688       { "Encoding Scheme",
2689         "sccp.calling.es",
2690         FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
2691         "", HFILL }},
2692     { &hf_sccp_calling_gt_digits,
2693       { "GT Digits",
2694         "sccp.calling.digits",
2695         FT_STRING, BASE_NONE, NULL, 0x0,
2696         "", HFILL }},
2697     { &hf_sccp_dlr,
2698       { "Destination Local Reference", "sccp.dlr",
2699         FT_UINT24, BASE_HEX, NULL, 0x0,
2700         "", HFILL}},
2701     { &hf_sccp_slr,
2702       { "Source Local Reference", "sccp.slr",
2703         FT_UINT24, BASE_HEX, NULL, 0x0,
2704         "", HFILL}},
2705     { &hf_sccp_lr,
2706     { "Local Reference", "sccp.lr",
2707       FT_UINT24, BASE_HEX, NULL, 0x0,
2708       "", HFILL}},
2709     { &hf_sccp_class,
2710       { "Class", "sccp.class",
2711         FT_UINT8, BASE_HEX, NULL, CLASS_CLASS_MASK,
2712         "", HFILL}},
2713     { &hf_sccp_handling,
2714       { "Message handling", "sccp.handling",
2715         FT_UINT8, BASE_HEX, VALS(sccp_class_handling_values), CLASS_SPARE_HANDLING_MASK,
2716         "", HFILL}},
2717     { &hf_sccp_more,
2718       { "More data", "sccp.more",
2719         FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEGMENTING_REASSEMBLING_MASK,
2720         "", HFILL}},
2721     { &hf_sccp_rsn,
2722       { "Receive Sequence Number", "sccp.rsn",
2723         FT_UINT8, BASE_HEX, NULL, RSN_MASK,
2724         "", HFILL}},
2725     { &hf_sccp_sequencing_segmenting_ssn,
2726       { "Sequencing Segmenting: Send Sequence Number", "sccp.sequencing_segmenting.ssn",
2727         FT_UINT8, BASE_HEX, NULL, SEND_SEQUENCE_NUMBER_MASK,
2728         "", HFILL}},
2729     { &hf_sccp_sequencing_segmenting_rsn,
2730       { "Sequencing Segmenting: Receive Sequence Number", "sccp.sequencing_segmenting.rsn",
2731         FT_UINT8, BASE_HEX, NULL, RECEIVE_SEQUENCE_NUMBER_MASK,
2732         "", HFILL}},
2733     { &hf_sccp_sequencing_segmenting_more,
2734       { "Sequencing Segmenting: More", "sccp.sequencing_segmenting.more",
2735         FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEQUENCING_SEGMENTING_MORE_MASK,
2736         "", HFILL}},
2737     { &hf_sccp_credit,
2738       { "Credit", "sccp.credit",
2739         FT_UINT8, BASE_HEX, NULL, 0x0,
2740         "", HFILL}},
2741     { &hf_sccp_release_cause,
2742       { "Release Cause", "sccp.release_cause",
2743         FT_UINT8, BASE_HEX, VALS(sccp_release_cause_values), 0x0,
2744         "", HFILL}},
2745     { &hf_sccp_return_cause,
2746       { "Return Cause", "sccp.return_cause",
2747         FT_UINT8, BASE_HEX, VALS(sccp_return_cause_values), 0x0,
2748         "", HFILL}},
2749     { &hf_sccp_reset_cause,
2750       { "Reset Cause", "sccp.reset_cause",
2751         FT_UINT8, BASE_HEX, VALS(sccp_reset_cause_values), 0x0,
2752         "", HFILL}},
2753     { &hf_sccp_error_cause,
2754       { "Error Cause", "sccp.error_cause",
2755         FT_UINT8, BASE_HEX, VALS(sccp_error_cause_values), 0x0,
2756         "", HFILL}},
2757     { &hf_sccp_refusal_cause,
2758       { "Refusal Cause", "sccp.refusal_cause",
2759         FT_UINT8, BASE_HEX, VALS(sccp_refusal_cause_values), 0x0,
2760         "", HFILL}},
2761     { &hf_sccp_segmentation_first,
2762       { "Segmentation: First", "sccp.segmentation.first",
2763         FT_UINT8, BASE_HEX, VALS(sccp_segmentation_first_segment_values), SEGMENTATION_FIRST_SEGMENT_MASK,
2764         "", HFILL}},
2765     { &hf_sccp_segmentation_class,
2766       { "Segmentation: Class", "sccp.segmentation.class",
2767         FT_UINT8, BASE_HEX, VALS(sccp_segmentation_class_values), SEGMENTATION_CLASS_MASK,
2768         "", HFILL}},
2769     { &hf_sccp_segmentation_remaining,
2770       { "Segmentation: Remaining", "sccp.segmentation.remaining",
2771         FT_UINT8, BASE_HEX, NULL, SEGMENTATION_REMAINING_MASK,
2772         "", HFILL}},
2773     { &hf_sccp_segmentation_slr,
2774       { "Segmentation: Source Local Reference", "sccp.segmentation.slr",
2775         FT_UINT24, BASE_HEX, NULL, 0x0,
2776         "", HFILL}},
2777     { &hf_sccp_hop_counter,
2778       { "Hop Counter", "sccp.hops",
2779         FT_UINT8, BASE_HEX, NULL, 0x0,
2780         "", HFILL}},
2781     { &hf_sccp_importance,
2782       { "Importance", "sccp.importance",
2783         FT_UINT8, BASE_HEX, NULL, IMPORTANCE_IMPORTANCE_MASK,
2784         "", HFILL}},
2785     /* ISNI is ANSI only */
2786     { &hf_sccp_ansi_isni_mi,
2787       { "ISNI Mark for Identification Indicator", "sccp.isni.mi",
2788         FT_UINT8, BASE_HEX, VALS(sccp_isni_mark_for_id_values), ANSI_ISNI_MI_MASK,
2789         "", HFILL}},
2790     { &hf_sccp_ansi_isni_iri,
2791       { "ISNI Routing Indicator", "sccp.isni.iri",
2792         FT_UINT8, BASE_HEX, VALS(sccp_isni_iri_values), ANSI_ISNI_IRI_MASK,
2793         "", HFILL}},
2794     { &hf_sccp_ansi_isni_ti,
2795       { "ISNI Type Indicator", "sccp.isni.ti",
2796         FT_UINT8, BASE_HEX, VALS(sccp_isni_ti_values), ANSI_ISNI_TI_MASK,
2797         "", HFILL}},
2798     { &hf_sccp_ansi_isni_netspec,
2799       { "ISNI Network Specific (Type 1)", "sccp.isni.netspec",
2800         FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_NETSPEC_MASK,
2801         "", HFILL}},
2802     { &hf_sccp_ansi_isni_counter,
2803       { "ISNI Counter", "sccp.isni.counter",
2804         FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_COUNTER_MASK,
2805         "", HFILL}},
2806     {&hf_sccp_xudt_msg_fragments,
2807         {"Message fragments", "sccp.msg.fragments",
2808         FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }
2809     },
2810     {&hf_sccp_xudt_msg_fragment,
2811         {"Message fragment", "sccp.msg.fragment",
2812         FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
2813     },
2814     {&hf_sccp_xudt_msg_fragment_overlap,
2815         {"Message fragment overlap", "sccp.msg.fragment.overlap",
2816         FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
2817     },
2818     {&hf_sccp_xudt_msg_fragment_overlap_conflicts,
2819         {"Message fragment overlapping with conflicting data", "sccp.msg.fragment.overlap.conflicts",
2820         FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
2821     },
2822     {&hf_sccp_xudt_msg_fragment_multiple_tails,
2823         {"Message has multiple tail fragments", "sccp.msg.fragment.multiple_tails",
2824         FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
2825     },
2826     {&hf_sccp_xudt_msg_fragment_too_long_fragment,
2827         {"Message fragment too long", "sccp.msg.fragment.too_long_fragment",
2828         FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
2829     },
2830     {&hf_sccp_xudt_msg_fragment_error,
2831         {"Message defragmentation error", "sccp.msg.fragment.error",
2832         FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
2833     },
2834     {&hf_sccp_xudt_msg_reassembled_in,
2835         {"Reassembled in", "sccp.msg.reassembled.in",
2836         FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
2837     },
2838     { &hf_sccp_assoc_id,
2839       { "Association ID", "sccp.assoc.id",
2840         FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
2841     {&hf_sccp_assoc_msg,
2842         {"Message in frame", "sccp.assoc.msg",
2843         FT_FRAMENUM, BASE_NONE, NULL, 0x00, "", HFILL }
2844     },
2845
2846   };
2847
2848   /* Setup protocol subtree array */
2849   static gint *ett[] = {
2850     &ett_sccp,
2851     &ett_sccp_called,
2852     &ett_sccp_called_ai,
2853     &ett_sccp_called_pc,
2854     &ett_sccp_called_gt,
2855     &ett_sccp_calling,
2856     &ett_sccp_calling_ai,
2857     &ett_sccp_calling_pc,
2858     &ett_sccp_calling_gt,
2859     &ett_sccp_sequencing_segmenting,
2860     &ett_sccp_segmentation,
2861     &ett_sccp_ansi_isni_routing_control,
2862     &ett_sccp_xudt_msg_fragment,
2863     &ett_sccp_xudt_msg_fragments,
2864     &ett_sccp_assoc
2865   };
2866
2867   /* Register the protocol name and description */
2868   proto_sccp = proto_register_protocol("Signalling Connection Control Part",
2869                                        "SCCP", "sccp");
2870
2871   register_dissector("sccp", dissect_sccp, proto_sccp);
2872
2873   /* Required function calls to register the header fields and subtrees used */
2874   proto_register_field_array(proto_sccp, hf, array_length(hf));
2875   proto_register_subtree_array(ett, array_length(ett));
2876
2877   sccp_ssn_dissector_table = register_dissector_table("sccp.ssn", "SCCP SSN", FT_UINT8, BASE_DEC);
2878
2879   register_heur_dissector_list("sccp", &heur_subdissector_list);
2880
2881   sccp_module = prefs_register_protocol(proto_sccp, NULL);
2882
2883   prefs_register_uint_preference(sccp_module, "source_pc",
2884                                  "Source PC",
2885                                  "The source point code (usually MSC) (to determine whether message is uplink or downlink)",
2886                                  16, &sccp_source_pc_global);
2887
2888   prefs_register_bool_preference(sccp_module, "show_length", "Show length",
2889                                  "Show parameter length in the protocol tree",
2890                                  &sccp_show_length);
2891
2892   prefs_register_bool_preference(sccp_module, "defragment_xudt",
2893                                  "Reassemble XUDT messages",
2894                                  "Whether XUDT messages should be reassembled",
2895                                  &sccp_xudt_desegment);
2896
2897   prefs_register_bool_preference(sccp_module, "trace_sccp",
2898                                  "Trace Associations",
2899                                  "Whether to keep infomation about messages and their associations",
2900                                  &trace_sccp);
2901
2902   
2903   prefs_register_bool_preference(sccp_module, "show_more_info",
2904                                                                  "Show key parameters in Info Column",
2905                                                                  "Show SLR, DLR, and CAUSE Parameters in the Information Column of the Summary",
2906                                                                  &show_key_params);
2907   
2908   
2909
2910   register_init_routine(&init_sccp);
2911
2912   assocs = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "sccp_associations");
2913
2914   sccp_tap = register_tap("sccp");
2915
2916 }
2917
2918 void
2919 proto_reg_handoff_sccp(void)
2920 {
2921   dissector_handle_t sccp_handle;
2922
2923   sccp_handle = find_dissector("sccp");
2924
2925   dissector_add("mtp3.service_indicator", SCCP_SI, sccp_handle);
2926   dissector_add_string("tali.opcode", "sccp", sccp_handle);
2927
2928   data_handle = find_dissector("data");
2929 }
2930