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