From Jeff Morriss:
[obnox/wireshark/wip.git] / packet-sccp.c
1 /* packet-sccp.c
2  * Routines for Signalling Connection Control Part (SCCP) dissection
3  * It is hopefully compliant to:
4  *   ANSI T1.112.3-1996
5  *   ITU-T Q.713 7/1996
6  *
7  * Copyright 2002, Jeff Morriss <jeff.morriss[AT]ulticom.com>
8  *
9  * $Id: packet-sccp.c,v 1.7 2003/01/02 20:44:32 guy Exp $
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@ethereal.com>
13  * Copyright 1998 Gerald Combs
14  *
15  * Copied from packet-m2pa.c
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License
19  * as published by the Free Software Foundation; either version 2
20  * of the License, or (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include <glib.h>
41
42 #ifdef NEED_SNPRINTF_H
43 #include "snprintf.h"
44 #endif
45
46 #include <epan/packet.h>
47 #include "packet-mtp3.h"
48
49 #define SCCP_SI 3
50
51 #define MESSAGE_TYPE_OFFSET 0
52 #define MESSAGE_TYPE_LENGTH 1
53 #define POINTER_LENGTH      1
54
55 #define MESSAGE_TYPE_CR    0x01
56 #define MESSAGE_TYPE_CC    0x02
57 #define MESSAGE_TYPE_CREF  0x03
58 #define MESSAGE_TYPE_RLSD  0x04
59 #define MESSAGE_TYPE_RLC   0x05
60 #define MESSAGE_TYPE_DT1   0x06
61 #define MESSAGE_TYPE_DT2   0x07
62 #define MESSAGE_TYPE_AK    0x08
63 #define MESSAGE_TYPE_UDT   0x09
64 #define MESSAGE_TYPE_UDTS  0x0a
65 #define MESSAGE_TYPE_ED    0x0b
66 #define MESSAGE_TYPE_EA    0x0c
67 #define MESSAGE_TYPE_RSR   0x0d
68 #define MESSAGE_TYPE_RSC   0x0e
69 #define MESSAGE_TYPE_ERR   0x0f
70 #define MESSAGE_TYPE_IT    0x10
71 #define MESSAGE_TYPE_XUDT  0x11
72 #define MESSAGE_TYPE_XUDTS 0x12
73 /* The below 2 are ITU only */
74 #define MESSAGE_TYPE_LUDT  0x13
75 #define MESSAGE_TYPE_LUDTS 0x14
76
77 /* Same as below but with names typed out */
78 static const value_string sccp_message_type_values[] = {
79   { MESSAGE_TYPE_CR,     "Connection Request" },
80   { MESSAGE_TYPE_CC,     "Connection Confirm" },
81   { MESSAGE_TYPE_CREF,   "Connection Refused" },
82   { MESSAGE_TYPE_RLSD,   "Released" },
83   { MESSAGE_TYPE_RLC,    "Release Complete" },
84   { MESSAGE_TYPE_DT1,    "Data Form 1" },
85   { MESSAGE_TYPE_DT2,    "Data Form 2" },
86   { MESSAGE_TYPE_AK,     "Data Acknowledgement" },
87   { MESSAGE_TYPE_UDT,    "Unitdata" },
88   { MESSAGE_TYPE_UDTS,   "Unitdata Service" },
89   { MESSAGE_TYPE_ED,     "Expedited Data" },
90   { MESSAGE_TYPE_EA,     "Expedited Data Acknowledgement" },
91   { MESSAGE_TYPE_RSR,    "Reset Request" },
92   { MESSAGE_TYPE_RSC,    "Reset Confirmation" },
93   { MESSAGE_TYPE_ERR,    "Error" },
94   { MESSAGE_TYPE_IT,     "Inactivity Timer" },
95   { MESSAGE_TYPE_XUDT,   "Extended Unitdata" },
96   { MESSAGE_TYPE_XUDTS,  "Extended Unitdata Service" },
97   { MESSAGE_TYPE_LUDT,   "Long Unitdata (ITU)" },
98   { MESSAGE_TYPE_LUDTS,  "Long Unitdata Service (ITU)" },
99   { 0,                   NULL } };
100
101 /* Same as above but in acronym form (for the Info column) */
102 static const value_string sccp_message_type_acro_values[] = {
103   { MESSAGE_TYPE_CR,     "CR" },
104   { MESSAGE_TYPE_CC,     "CC" },
105   { MESSAGE_TYPE_CREF,   "CREF" },
106   { MESSAGE_TYPE_RLSD,   "RLSD" },
107   { MESSAGE_TYPE_RLC,    "RLC" },
108   { MESSAGE_TYPE_DT1,    "DT1" },
109   { MESSAGE_TYPE_DT2,    "DT2" },
110   { MESSAGE_TYPE_AK,     "AK" },
111   { MESSAGE_TYPE_UDT,    "UDT" },
112   { MESSAGE_TYPE_UDTS,   "UDTS" },
113   { MESSAGE_TYPE_ED,     "ED" },
114   { MESSAGE_TYPE_EA,     "EA" },
115   { MESSAGE_TYPE_RSR,    "RSR" },
116   { MESSAGE_TYPE_RSC,    "RSC" },
117   { MESSAGE_TYPE_ERR,    "ERR" },
118   { MESSAGE_TYPE_IT,     "IT" },
119   { MESSAGE_TYPE_XUDT,   "XUDT" },
120   { MESSAGE_TYPE_XUDTS,  "XUDTS" },
121   { MESSAGE_TYPE_LUDT,   "LUDT" },
122   { MESSAGE_TYPE_LUDTS,  "LUDTS" },
123   { 0,                   NULL } };
124
125 #define PARAMETER_LENGTH_LENGTH 1
126 #define PARAMETER_LONG_DATA_LENGTH_LENGTH 2
127 #define PARAMETER_TYPE_LENGTH 1
128
129 #define PARAMETER_END_OF_OPTIONAL_PARAMETERS   0x00
130 #define PARAMETER_DESTINATION_LOCAL_REFERENCE  0x01
131 #define PARAMETER_SOURCE_LOCAL_REFERENCE       0x02
132 #define PARAMETER_CALLED_PARTY_ADDRESS         0x03
133 #define PARAMETER_CALLING_PARTY_ADDRESS        0x04
134 #define PARAMETER_CLASS                        0x05
135 #define PARAMETER_SEGMENTING_REASSEMBLING      0x06
136 #define PARAMETER_RECEIVE_SEQUENCE_NUMBER      0x07
137 #define PARAMETER_SEQUENCING_SEGMENTING        0x08
138 #define PARAMETER_CREDIT                       0x09
139 #define PARAMETER_RELEASE_CAUSE                0x0a
140 #define PARAMETER_RETURN_CAUSE                 0x0b
141 #define PARAMETER_RESET_CAUSE                  0x0c
142 #define PARAMETER_ERROR_CAUSE                  0x0d
143 #define PARAMETER_REFUSAL_CAUSE                0x0e
144 #define PARAMETER_DATA                         0x0f
145 #define PARAMETER_SEGMENTATION                 0x10
146 #define PARAMETER_HOP_COUNTER                  0x11
147 /* The below 2 are ITU only */
148 #define PARAMETER_IMPORTANCE                   0x12
149 #define PARAMETER_LONG_DATA                    0x13
150 /* ISNI is ANSI only */
151 #define PARAMETER_ISNI                         0xfa
152
153 static const value_string sccp_parameter_values[] = {
154   { PARAMETER_END_OF_OPTIONAL_PARAMETERS, "End of Optional Parameters" },
155   { PARAMETER_DESTINATION_LOCAL_REFERENCE, "Destination Local Reference" },
156   { PARAMETER_SOURCE_LOCAL_REFERENCE,     "Source Local Reference" },
157   { PARAMETER_CALLED_PARTY_ADDRESS,       "Called Party Address" },
158   { PARAMETER_CALLING_PARTY_ADDRESS,      "Calling Party Address" },
159   { PARAMETER_CLASS,                      "Protocol Class" },
160   { PARAMETER_SEGMENTING_REASSEMBLING,    "Segmenting/Reassembling" },
161   { PARAMETER_RECEIVE_SEQUENCE_NUMBER,    "Receive Sequence Number" },
162   { PARAMETER_SEQUENCING_SEGMENTING,      "Sequencing/Segmenting" },
163   { PARAMETER_CREDIT,                     "Credit" },
164   { PARAMETER_RELEASE_CAUSE,              "Release Cause" },
165   { PARAMETER_RETURN_CAUSE,               "Return Cause" },
166   { PARAMETER_RESET_CAUSE,                "Reset Cause" },
167   { PARAMETER_ERROR_CAUSE,                "Error Cause" },
168   { PARAMETER_REFUSAL_CAUSE,              "Refusal Cause" },
169   { PARAMETER_DATA,                       "Data" },
170   { PARAMETER_SEGMENTATION,               "Segmentation" },
171   { PARAMETER_HOP_COUNTER,                "Hop Counter" },
172   { PARAMETER_IMPORTANCE,                 "Importance (ITU)" },
173   { PARAMETER_LONG_DATA,                  "Long Data (ITU)" },
174   { PARAMETER_ISNI,                       "Intermediate Signaling Network Identification (ANSI)" },
175   { 0,                                    NULL } };
176
177
178 #define END_OF_OPTIONAL_PARAMETERS_LENGTH   1
179 #define DESTINATION_LOCAL_REFERENCE_LENGTH  3
180 #define SOURCE_LOCAL_REFERENCE_LENGTH       3
181 #define PROTOCOL_CLASS_LENGTH               1
182 #define RECEIVE_SEQUENCE_NUMBER_LENGTH      1
183 #define CREDIT_LENGTH                       1
184 #define RELEASE_CAUSE_LENGTH                1
185 #define RETURN_CAUSE_LENGTH                 1
186 #define RESET_CAUSE_LENGTH                  1
187 #define ERROR_CAUSE_LENGTH                  1
188 #define REFUSAL_CAUSE_LENGTH                1
189 #define HOP_COUNTER_LENGTH                  1
190 #define IMPORTANCE_LENGTH                   1
191
192
193 /* Parts of the Called and Calling Address parameters */
194 /* Address Indicator */
195 #define ADDRESS_INDICATOR_LENGTH   1
196 #define ITU_RESERVED_MASK          0x80
197 #define ANSI_NATIONAL_MASK         0x80
198 #define ROUTING_INDICATOR_MASK     0x40
199 #define GTI_MASK                   0x3C
200 #define GTI_SHIFT                  2
201 #define ITU_SSN_INDICATOR_MASK     0x02
202 #define ITU_PC_INDICATOR_MASK      0x01
203 #define ANSI_PC_INDICATOR_MASK     0x02
204 #define ANSI_SSN_INDICATOR_MASK    0x01
205
206 static const value_string sccp_national_indicator_values[] = {
207   { 0x0,  "Address coded to International standard" },
208   { 0x1,  "Address coded to National standard" },
209   { 0,    NULL } };
210
211 static const value_string sccp_routing_indicator_values[] = {
212   { 0x0, "Route on GT" },
213   { 0x1, "Route on SSN" },
214   { 0,   NULL } };
215
216 #define AI_GTI_NO_GT             0x0
217 #define ITU_AI_GTI_NAI           0x1
218 #define AI_GTI_TT                0x2
219 #define ITU_AI_GTI_TT_NP_ES      0x3
220 #define ITU_AI_GTI_TT_NP_ES_NAI  0x4
221 static const value_string sccp_itu_global_title_indicator_values[] = {
222   { AI_GTI_NO_GT,             "No Global Title" },
223   { ITU_AI_GTI_NAI,           "Nature of Address Indicator only" },
224   { AI_GTI_TT,                "Translation Type only" },
225   { ITU_AI_GTI_TT_NP_ES,      "Translation Type, Numbering Plan, and Encoding Scheme included" },
226   { ITU_AI_GTI_TT_NP_ES_NAI,  "Translation Type, Numbering Plan, Encoding Scheme, and Nature of Address Indicator included" },
227   { 0,                        NULL } };
228
229 /* #define AI_GTI_NO_GT     0x0 */
230 #define ANSI_AI_GTI_TT_NP_ES  0x1
231 /* #define AI_GTI_TT          0x2 */
232 static const value_string sccp_ansi_global_title_indicator_values[] = {
233   { AI_GTI_NO_GT,          "No Global Title" },
234   { ANSI_AI_GTI_TT_NP_ES,  "Translation Type, Numbering Plan, and Encoding Scheme included" },
235   { AI_GTI_TT,             "Translation Type only" },
236   { 0,                     NULL } };
237
238 static const value_string sccp_ai_pci_values[] = {
239   { 0x1,  "Point Code present" },
240   { 0x0,  "Point Code not present" },
241   { 0,    NULL } };
242
243 static const value_string sccp_ai_ssni_values[] = {
244   { 0x1,  "SSN present" },
245   { 0x0,  "SSN not present" },
246   { 0,    NULL } };
247
248 #define ADDRESS_SSN_LENGTH    1
249 #define INVALID_SSN 0xff
250 static const value_string sccp_ssn_values[] = {
251   { 0x00,  "SSN not known/not used" },
252   { 0x01,  "SCCP management" },
253   { 0x02,  "Reserved for ITU-T allocation" },
254   { 0x03,  "ISDN User Part" },
255   { 0x04,  "OMAP (Operation, Maintenance, and Administration Part)" },
256   { 0x05,  "MAP (Mobile Application Part)" },
257   { 0x06,  "HLR (Home Location Register)" },
258   { 0x07,  "VLR (Visitor Location Register)" },
259   { 0x08,  "MSC (Mobile Switching Center)" },
260   { 0x09,  "EIC/EIR (Equipment Identifier Center/Equipment Identification Register)" },
261   { 0x0a,  "AUC/AC (Authentication Center)" },
262   { 0x0b,  "ISDN supplementary services (ITU only)" },
263   { 0x0c,  "Reserved for international use (ITU only)" },
264   { 0x0d,  "Broadband ISDN edge-to-edge applications (ITU only)" },
265   { 0x0e,  "TC test responder (ITU only)" },
266   { 0,     NULL } };
267
268
269 /* * * * * * * * * * * * * * * * *
270  * Global Title: ITU GTI == 0001 *
271  * * * * * * * * * * * * * * * * */
272 #define GT_NAI_MASK 0x7F
273 #define GT_NAI_LENGTH 1
274 static const value_string sccp_nai_values[] = {
275   { 0x00,  "NAI unknown" },
276   { 0x01,  "Subscriber Number" },
277   { 0x02,  "Reserved for national use" },
278   { 0x03,  "National significant number" },
279   { 0x04,  "International number" },
280   { 0,     NULL } };
281
282
283 #define GT_OE_MASK 0x80
284 #define GT_OE_EVEN 0
285 #define GT_OE_ODD  1
286 static const value_string sccp_oe_values[] = {
287   { GT_OE_EVEN,  "Even number of address signals" },
288   { GT_OE_ODD,   "Odd number of address signals" },
289   { 0,           NULL } };
290
291 #define GT_SIGNAL_LENGTH     1
292 #define GT_ODD_SIGNAL_MASK   0x0f
293 #define GT_EVEN_SIGNAL_MASK  0xf0
294 #define GT_EVEN_SIGNAL_SHIFT 4
295 #define GT_MAX_SIGNALS 32
296 static const value_string sccp_address_signal_values[] = {
297   { 0,  "0" },
298   { 1,  "1" },
299   { 2,  "2" },
300   { 3,  "3" },
301   { 4,  "4" },
302   { 5,  "5" },
303   { 6,  "6" },
304   { 7,  "7" },
305   { 8,  "8" },
306   { 9,  "9" },
307   { 10, "(spare)" },
308   { 11, "11" },
309   { 12, "12" },
310   { 13, "(spare)" },
311   { 14, "(spare)" },
312   { 15, "ST" },
313   { 0,  NULL } };
314
315
316 /* * * * * * * * * * * * * * * * * * * * *
317  * Global Title: ITU and ANSI GTI == 0010 *
318  * * * * * * * * * * * * * * * * * * * * */
319 #define GT_TT_LENGTH 1
320
321
322 /* * * * * * * * * * * * * * * * * * * * * * * * * *
323  * Global Title: ITU GTI == 0011, ANSI GTI == 0001 *
324  * * * * * * * * * * * * * * * * * * * * * * * * * */
325 #define GT_NP_MASK 0xf0
326 #define GT_NP_ES_LENGTH 1
327 static const value_string sccp_np_values[] = {
328   { 0x0,  "Unknown" },
329   { 0x1,  "ISDN/telephony" },
330   { 0x2,  "Generic (ITU)/Reserved (ANSI)" },
331   { 0x3,  "Data" },
332   { 0x4,  "Telex" },
333   { 0x5,  "Maritime mobile" },
334   { 0x6,  "Land mobile" },
335   { 0x7,  "ISDN/mobile" },
336   { 0xe,  "Private network or network-specific" },
337   { 0xf,  "Reserved" },
338   { 0,    NULL } };
339
340 #define GT_ES_MASK     0x0f
341 #define GT_ES_UNKNOWN  0x0
342 #define GT_ES_BCD_ODD  0x1
343 #define GT_ES_BCD_EVEN 0x2
344 #define GT_ES_NATIONAL 0x3
345 #define GT_ES_RESERVED 0xf
346 static const value_string sccp_es_values[] = {
347   { GT_ES_UNKNOWN,  "Unknown" },
348   { GT_ES_BCD_ODD,  "BCD, odd number of digits" },
349   { GT_ES_BCD_EVEN, "BCD, even number of digits" },
350   { GT_ES_NATIONAL, "National specific" },
351   { GT_ES_RESERVED, "Reserved (ITU)/Spare (ANSI)" },
352   { 0,           NULL } };
353
354 /* Address signals above */
355
356
357 /* * * * * * * * * * * * * * * * *
358  * Global Title: ITU GTI == 0100 *
359  * * * * * * * * * * * * * * * * */
360 /* NP above */
361 /* ES above */
362 /* NAI above */
363 /* Address signals above */
364
365
366 #define CLASS_CLASS_MASK 0xf
367 #define CLASS_SPARE_HANDLING_MASK 0xf0
368 static const value_string sccp_class_handling_values [] = {
369   { 0x0,  "No special options" },
370   { 0x8,  "Return message on error" },
371   { 0,    NULL } };
372
373
374 #define SEGMENTING_REASSEMBLING_LENGTH 1
375 #define SEGMENTING_REASSEMBLING_MASK   0x01
376 #define NO_MORE_DATA 0
377 #define MORE_DATA    1
378 /* This is also used by sequencing-segmenting parameter */
379 static const value_string sccp_segmenting_reassembling_values [] = {
380   { NO_MORE_DATA, "No more data" },
381   { MORE_DATA,    "More data" },
382   { 0,            NULL } };
383
384
385 #define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
386 #define RSN_MASK                       0xfe
387
388 #define SEQUENCING_SEGMENTING_LENGTH    2
389 #define SEQUENCING_SEGMENTING_SSN_LENGTH 1
390 #define SEQUENCING_SEGMENTING_RSN_LENGTH 1
391 #define SEND_SEQUENCE_NUMBER_MASK       0xfe
392 #define RECEIVE_SEQUENCE_NUMBER_MASK    0xfe
393 #define SEQUENCING_SEGMENTING_MORE_MASK 0x01
394
395
396 #define CREDIT_LENGTH 1
397
398 #define RELEASE_CAUSE_LENGTH                  1
399 static const value_string sccp_release_cause_values [] = {
400   { 0x00,  "End user originated" },
401   { 0x01,  "End user congestion" },
402   { 0x02,  "End user failure" },
403   { 0x03,  "SCCP user originated" },
404   { 0x04,  "Remote procedure error" },
405   { 0x05,  "Inconsistent connection data" },
406   { 0x06,  "Access failure" },
407   { 0x07,  "Access congestion" },
408   { 0x08,  "Subsystem failure" },
409   { 0x09,  "Subsystem congestion" },
410   { 0x0a,  "MTP failure" },
411   { 0x0b,  "Netowrk congestion" },
412   { 0x0c,  "Expiration of reset timer" },
413   { 0x0d,  "Expiration of receive inactivity timer" },
414   { 0x0e,  "Reserved" },
415   { 0x0f,  "Unqualified" },
416   { 0x10,  "SCCP failure (ITU only)" },
417   { 0,     NULL } };
418
419
420 #define RETURN_CAUSE_LENGTH               1
421 static const value_string sccp_return_cause_values [] = {
422   { 0x00,  "No translation for an address of such nature" },
423   { 0x01,  "No translation for this specific address" },
424   { 0x02,  "Subsystem congestion" },
425   { 0x03,  "Subsystem failure" },
426   { 0x04,  "Unequipped failure" },
427   { 0x05,  "MTP failure" },
428   { 0x06,  "Network congestion" },
429   { 0x07,  "Unqualified" },
430   { 0x08,  "Error in message transport" },
431   { 0x09,  "Error in local processing" },
432   { 0x0a,  "Destination cannot perform reassembly" },
433   { 0x0b,  "SCCP failure" },
434   { 0x0c,  "Hop counter violation" },
435   { 0x0d,  "Segmentation not supported (ITU only)" },
436   { 0x0e,  "Segmentation failure (ITU only)" },
437   { 0xf9,  "Invalid ISNI routing request (ANSI only)"},
438   { 0xfa,  "Unauthorized message (ANSI only)" },
439   { 0xfb,  "Message incompatibility (ANSI only)" },
440   { 0xfc,  "Cannot perform ISNI constrained routing (ANSI only)" },
441   { 0xfd,  "Unable to perform ISNI identification (ANSI only)" },
442   { 0,     NULL } };
443
444
445 #define RESET_CAUSE_LENGTH                 1
446 static const value_string sccp_reset_cause_values [] = {
447   { 0x00,  "End user originated" },
448   { 0x01,  "SCCP user originated" },
449   { 0x02,  "Message out of order - incorrect send sequence number" },
450   { 0x03,  "Message out of order - incorrect receive sequence number" },
451   { 0x04,  "Remote procedure error - message out of window" },
452   { 0x05,  "Remote procedure error - incorrect send sequence number after (re)initialization" },
453   { 0x06,  "Remote procedure error - general" },
454   { 0x07,  "Remote end user operational" },
455   { 0x08,  "Network operational" },
456   { 0x09,  "Access operational" },
457   { 0x0a,  "Network congestion" },
458   { 0x0b,  "Reserved (ITU)/Not obtainable (ANSI)" },
459   { 0x0c,  "Unqualified" },
460   { 0,     NULL } };
461
462
463 #define ERROR_CAUSE_LENGTH      1
464 static const value_string sccp_error_cause_values [] = {
465   { 0x00,  "Local Reference Number (LRN) mismatch - unassigned destination LRN" },
466   { 0x01,  "Local Reference Number (LRN) mismatch - inconsistent source LRN" },
467   { 0x02,  "Point code mismatch" },
468   { 0x03,  "Service class mismatch" },
469   { 0x04,  "Unqualified" },
470   { 0,     NULL } };
471
472
473 #define REFUSAL_CAUSE_LENGTH                     1
474 static const value_string sccp_refusal_cause_values [] = {
475   { 0x00,  "End user originated" },
476   { 0x01,  "End user congestion" },
477   { 0x02,  "End user failure" },
478   { 0x03,  "SCCP user originated" },
479   { 0x04,  "Destination address unknown" },
480   { 0x05,  "Destination inaccessible" },
481   { 0x06,  "Network resource - QOS not available/non-transient" },
482   { 0x07,  "Network resource - QOS not available/transient" },
483   { 0x08,  "Access failure" },
484   { 0x09,  "Access congestion" },
485   { 0x0a,  "Subsystem failure" },
486   { 0x0b,  "Subsystem congestion" },
487   { 0x0c,  "Expiration of connection establishment timer" },
488   { 0x0d,  "Incompatible user data" },
489   { 0x0e,  "Reserved" },
490   { 0x0f,  "Unqualified" },
491   { 0x10,  "Hop counter violation" },
492   { 0x11,  "SCCP failure (ITU only)" },
493   { 0x12,  "No translation for an address of such nature" },
494   { 0x13,  "Unequipped user" },
495   { 0,     NULL } };
496
497
498 #define SEGMENTATION_LENGTH              4
499 #define SEGMENTATION_FIRST_SEGMENT_MASK  0x80
500 #define SEGMENTATION_CLASS_MASK          0x40
501 #define SEGMENTATION_SPARE_MASK          0x30
502 #define SEGMENTATION_REMAINING_MASK      0x0f
503 static const value_string sccp_segmentation_first_segment_values [] = {
504   { 1,  "First segment" },
505   { 0,  "Not first segment" },
506   { 0,  NULL } };
507 static const value_string sccp_segmentation_class_values [] = {
508   { 0,  "Class 0 selected" },
509   { 1,  "Class 1 selected" },
510   { 0,  NULL } };
511
512
513 #define HOP_COUNTER_LENGTH 1
514
515 #define IMPORTANCE_LENGTH          1
516 #define IMPORTANCE_IMPORTANCE_MASK 0x7
517
518
519 #define ANSI_ISNI_ROUTING_CONTROL_LENGTH 1
520 #define ANSI_ISNI_MI_MASK                0x01
521 #define ANSI_ISNI_IRI_MASK               0x06
522 #define ANSI_ISNI_RES_MASK               0x08
523 #define ANSI_ISNI_TI_MASK                0x10
524 #define ANSI_ISNI_TI_SHIFT               4
525 #define ANSI_ISNI_COUNTER_MASK           0xe0
526
527 #define ANSI_ISNI_NETSPEC_MASK           0x03
528
529 static const value_string sccp_isni_mark_for_id_values [] = {
530   { 0x0,  "Do not identify networks" },
531   { 0x1,  "Identify networks" },
532   { 0,    NULL } };
533
534 static const value_string sccp_isni_iri_values [] = {
535   { 0x0,  "Neither constrained nor suggested ISNI routing" },
536   { 0x1,  "Constrained ISNI routing" },
537   { 0x2,  "Reserved for suggested ISNI routing" },
538   { 0x3,  "Spare" },
539   { 0,    NULL } };
540
541 #define ANSI_ISNI_TYPE_0 0x0
542 #define ANSI_ISNI_TYPE_1 0x1
543 static const value_string sccp_isni_ti_values [] = {
544   { ANSI_ISNI_TYPE_0,  "Type zero ISNI parameter format" },
545   { ANSI_ISNI_TYPE_1,  "Type one ISNI parameter format" },
546   { 0,                 NULL } };
547
548
549 /* Initialize the protocol and registered fields */
550 static int proto_sccp = -1;
551 static int hf_sccp_message_type = -1;
552 static int hf_sccp_variable_pointer1 = -1;
553 static int hf_sccp_variable_pointer2 = -1;
554 static int hf_sccp_variable_pointer3 = -1;
555 static int hf_sccp_optional_pointer = -1;
556 static int hf_sccp_ssn = -1;
557 static int hf_sccp_gt_digits = -1;
558
559 /* Called Party address */
560 static int hf_sccp_called_national_indicator = -1;
561 static int hf_sccp_called_routing_indicator = -1;
562 static int hf_sccp_called_itu_global_title_indicator = -1;
563 static int hf_sccp_called_ansi_global_title_indicator = -1;
564 static int hf_sccp_called_itu_ssn_indicator = -1;
565 static int hf_sccp_called_itu_point_code_indicator = -1;
566 static int hf_sccp_called_ansi_ssn_indicator = -1;
567 static int hf_sccp_called_ansi_point_code_indicator = -1;
568 static int hf_sccp_called_ssn = -1;
569 static int hf_sccp_called_pc_member = -1;
570 static int hf_sccp_called_pc_cluster = -1;
571 static int hf_sccp_called_pc_network = -1;
572 static int hf_sccp_called_ansi_pc = -1;
573 static int hf_sccp_called_itu_pc = -1;
574 static int hf_sccp_called_gt_nai = -1;
575 static int hf_sccp_called_gt_oe = -1;
576 static int hf_sccp_called_gt_tt = -1;
577 static int hf_sccp_called_gt_np = -1;
578 static int hf_sccp_called_gt_es = -1;
579 static int hf_sccp_called_gt_digits = -1;
580
581 /* Calling party address */
582 static int hf_sccp_calling_national_indicator = -1;
583 static int hf_sccp_calling_routing_indicator = -1;
584 static int hf_sccp_calling_itu_global_title_indicator = -1;
585 static int hf_sccp_calling_ansi_global_title_indicator = -1;
586 static int hf_sccp_calling_itu_ssn_indicator = -1;
587 static int hf_sccp_calling_itu_point_code_indicator = -1;
588 static int hf_sccp_calling_ansi_ssn_indicator = -1;
589 static int hf_sccp_calling_ansi_point_code_indicator = -1;
590 static int hf_sccp_calling_ssn = -1;
591 static int hf_sccp_calling_pc_member = -1;
592 static int hf_sccp_calling_pc_cluster = -1;
593 static int hf_sccp_calling_pc_network = -1;
594 static int hf_sccp_calling_ansi_pc = -1;
595 static int hf_sccp_calling_itu_pc = -1;
596 static int hf_sccp_calling_gt_nai = -1;
597 static int hf_sccp_calling_gt_oe = -1;
598 static int hf_sccp_calling_gt_tt = -1;
599 static int hf_sccp_calling_gt_np = -1;
600 static int hf_sccp_calling_gt_es = -1;
601 static int hf_sccp_calling_gt_digits = -1;
602
603 /* Other parameter values */
604 static int hf_sccp_dlr = -1;
605 static int hf_sccp_slr = -1;
606 static int hf_sccp_class = -1;
607 static int hf_sccp_handling = -1;
608 static int hf_sccp_more = -1;
609 static int hf_sccp_rsn = -1;
610 static int hf_sccp_sequencing_segmenting_ssn = -1;
611 static int hf_sccp_sequencing_segmenting_rsn = -1;
612 static int hf_sccp_sequencing_segmenting_more = -1;
613 static int hf_sccp_credit = -1;
614 static int hf_sccp_release_cause = -1;
615 static int hf_sccp_return_cause = -1;
616 static int hf_sccp_reset_cause = -1;
617 static int hf_sccp_error_cause = -1;
618 static int hf_sccp_refusal_cause = -1;
619 static int hf_sccp_segmentation_first = -1;
620 static int hf_sccp_segmentation_class = -1;
621 static int hf_sccp_segmentation_remaining = -1;
622 static int hf_sccp_segmentation_slr = -1;
623 static int hf_sccp_hop_counter = -1;
624 static int hf_sccp_importance = -1;
625 static int hf_sccp_ansi_isni_mi = -1;
626 static int hf_sccp_ansi_isni_iri = -1;
627 static int hf_sccp_ansi_isni_ti = -1;
628 static int hf_sccp_ansi_isni_netspec = -1;
629 static int hf_sccp_ansi_isni_counter = -1;
630
631
632 /* Initialize the subtree pointers */
633 static gint ett_sccp = -1;
634 static gint ett_sccp_called = -1;
635 static gint ett_sccp_called_ai = -1;
636 static gint ett_sccp_called_pc = -1;
637 static gint ett_sccp_called_gt = -1;
638 static gint ett_sccp_calling = -1;
639 static gint ett_sccp_calling_ai = -1;
640 static gint ett_sccp_calling_pc = -1;
641 static gint ett_sccp_calling_gt = -1;
642 static gint ett_sccp_sequencing_segmenting = -1;
643 static gint ett_sccp_segmentation = -1;
644 static gint ett_sccp_ansi_isni_routing_control = -1;
645
646
647 /*  Keep track of SSN value of current message so if/when we get to the data
648  *  parameter, we can call appropriate sub-dissector.  TODO: can this info
649  *  be stored elsewhere?
650  */
651 static guint8 called_ssn = INVALID_SSN;
652 static guint8 calling_ssn = INVALID_SSN;
653
654 static dissector_handle_t data_handle;
655 static dissector_table_t sccp_ssn_dissector_table;
656
657 static void
658 dissect_sccp_unknown_message(tvbuff_t *message_tvb, proto_tree *sccp_tree)
659 {
660   guint32 message_length;
661
662   message_length = tvb_length(message_tvb);
663
664   proto_tree_add_text(sccp_tree, message_tvb, 0, message_length,
665                       "Unknown message (%u byte%s)",
666                       message_length, plurality(message_length, "", "s"));
667 }
668
669 static void
670 dissect_sccp_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint16 length)
671 {
672   proto_tree_add_text(tree, tvb, 0, length, "Unknown parameter 0x%x (%u byte%s)",
673                       type, length, plurality(length, "", "s"));
674 }
675
676 static void
677 dissect_sccp_dlr_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
678 {
679   guint32 reference;
680
681   reference = tvb_get_ntoh24(tvb, 0);
682   proto_tree_add_uint(tree, hf_sccp_dlr, tvb, 0, length, reference);
683 }
684
685 static void
686 dissect_sccp_slr_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
687 {
688   guint32 reference;
689
690   reference = tvb_get_ntoh24(tvb, 0);
691   proto_tree_add_uint(tree, hf_sccp_slr, tvb, 0, length, reference);
692 }
693
694 static void
695 dissect_sccp_gt_address_information(tvbuff_t *tvb, proto_tree *tree,
696                                     guint8 length, gboolean even_length,
697                                     gboolean called)
698 {
699   guint8 offset = 0;
700   guint8 odd_signal, even_signal = 0x0f;
701   char gt_digits[GT_MAX_SIGNALS] = { 0 };
702
703   while(offset < length)
704   {
705     odd_signal = tvb_get_guint8(tvb, offset) & GT_ODD_SIGNAL_MASK;
706     even_signal = tvb_get_guint8(tvb, offset) & GT_EVEN_SIGNAL_MASK;
707     even_signal >>= GT_EVEN_SIGNAL_SHIFT;
708
709     strcat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values,
710                                  "Unknown"));
711
712     /* If the last signal is NOT filler */
713     if (offset != (length - 1) || even_length == TRUE)
714       strcat(gt_digits, val_to_str(even_signal, sccp_address_signal_values,
715                                    "Unknown"));
716
717     offset += GT_SIGNAL_LENGTH;
718   }
719
720   proto_tree_add_string_format(tree, called ? hf_sccp_called_gt_digits
721                                             : hf_sccp_calling_gt_digits,
722                              tvb, 0, length,
723                              gt_digits,
724                              "Address information (digits): %s", gt_digits);
725   proto_tree_add_string_hidden(tree, called ? hf_sccp_gt_digits
726                                             : hf_sccp_gt_digits,
727                              tvb, 0, length,
728                              gt_digits);
729 }
730
731 static void
732 dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint8 length,
733                           guint8 gti, gboolean called)
734 {
735   proto_item *gt_item = 0;
736   proto_tree *gt_tree = 0;
737   tvbuff_t *signals_tvb;
738   guint8 offset = 0;
739   guint8 odd_even, nai, tt, np, es;
740   gboolean even = TRUE;
741
742   /* Shift GTI to where we can work with it */
743   gti >>= GTI_SHIFT;
744
745   gt_item = proto_tree_add_text(tree, tvb, offset, length,
746                                 "Global Title 0x%x (%u byte%s)",
747                                 gti, length, plurality(length,"", "s"));
748   gt_tree = proto_item_add_subtree(gt_item, called ? ett_sccp_called_gt
749                                                    : ett_sccp_calling_gt);
750
751   /* Decode Transation Type (if present) */
752   switch (gti) {
753   case AI_GTI_TT:
754
755     /* Protocol doesn't tell us, so we ASSUME even... */
756     even = TRUE;
757     /* Fall through */
758   case ITU_AI_GTI_TT_NP_ES:
759   case ITU_AI_GTI_TT_NP_ES_NAI:
760   case ANSI_AI_GTI_TT_NP_ES:
761
762     tt = tvb_get_guint8(tvb, offset);
763     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_tt
764                                         : hf_sccp_calling_gt_tt,
765                         tvb, offset, GT_TT_LENGTH, tt);
766     offset += GT_TT_LENGTH;
767   }
768
769   /* Decode Numbering Plan and Encoding Scheme (if present) */
770   switch (gti) {
771   case ITU_AI_GTI_TT_NP_ES:
772   case ITU_AI_GTI_TT_NP_ES_NAI:
773   case ANSI_AI_GTI_TT_NP_ES:
774
775     np = tvb_get_guint8(tvb, offset) & GT_NP_MASK;
776     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_np
777                                         : hf_sccp_calling_gt_np,
778                         tvb, offset, GT_NP_ES_LENGTH, np);
779
780     es = tvb_get_guint8(tvb, offset) & GT_ES_MASK;
781     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_es
782                                         : hf_sccp_calling_gt_es,
783                         tvb, offset, GT_NP_ES_LENGTH, es);
784
785     even = (es == GT_ES_BCD_EVEN) ? TRUE : FALSE;
786
787     offset += GT_NP_ES_LENGTH;
788   }
789
790   /* Decode Odd/Even Indicator (if present) */
791   if (gti == ITU_AI_GTI_NAI) {
792     odd_even = tvb_get_guint8(tvb, offset) & GT_OE_MASK;
793     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_oe
794                                         : hf_sccp_calling_gt_oe,
795                         tvb, offset, GT_NAI_LENGTH, odd_even);
796     even = (odd_even == GT_OE_EVEN) ? TRUE : FALSE;
797
798     /* offset doesn't change */
799   }
800
801   /* Decode Nature of Address Indicator (if present) */
802   switch (gti) {
803   case ITU_AI_GTI_NAI:
804   case ITU_AI_GTI_TT_NP_ES_NAI:
805     nai = tvb_get_guint8(tvb, offset) & GT_NAI_MASK;
806     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_nai
807                                         : hf_sccp_calling_gt_nai,
808                         tvb, offset, GT_NAI_LENGTH, nai);
809
810     offset += GT_NAI_LENGTH;
811   }
812
813   /* Decode address signal(s) */
814   signals_tvb = tvb_new_subset(tvb, offset, (length - offset),
815                                (length - offset));
816   dissect_sccp_gt_address_information(signals_tvb, gt_tree, (length - offset),
817                                       even,
818                                       called);
819 }
820
821 /*  FUNCTION dissect_sccp_called_calling_param():
822  *  Dissect the Calling or Called Party Address parameters.
823  *
824  *  The boolean 'called' describes whether this function is decoding a
825  *  called (TRUE) or calling (FALSE) party address.  There is simply too
826  *  much code in this function to have 2 copies of it (one for called, one
827  *  for calling).
828  *
829  *  NOTE:  this function is called even when (!tree) so that we can get
830  *  the SSN and subsequently call subdissectors (if and when there's a data
831  *  parameter).  Realistically we should put if (!tree)'s around a lot of the
832  *  code, but I think that would make it unreadable--and the expense of not
833  *  doing so does not appear to be very high.
834  */
835 static void
836 dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree,
837                                   guint8 length, gboolean called)
838 {
839   proto_item *call_item = 0, *call_ai_item = 0, *call_pc_item = 0;
840   proto_tree *call_tree = 0, *call_ai_tree = 0, *call_pc_tree = 0;
841   guint8 offset;
842   guint8 national = -1, routing_ind, gti, pci, ssni, ssn;
843   guint32 dpc;
844   tvbuff_t *gt_tvb;
845   char pc[ANSI_PC_STRING_LENGTH];
846
847   call_item = proto_tree_add_text(tree, tvb, 0, length,
848                                     "%s Party address (%u byte%s)",
849                                     called ? "Called" : "Calling", length,
850                                     plurality(length, "", "s"));
851   call_tree = proto_item_add_subtree(call_item, called ? ett_sccp_called
852                                                        : ett_sccp_calling);
853
854   call_ai_item = proto_tree_add_text(call_tree, tvb, 0,
855                                        ADDRESS_INDICATOR_LENGTH,
856                                        "Address Indicator");
857   call_ai_tree = proto_item_add_subtree(call_ai_item, called ? ett_sccp_called_ai
858                                                              : ett_sccp_calling_ai);
859
860   if (mtp3_standard == ANSI_STANDARD)
861   {
862     national = tvb_get_guint8(tvb, 0) & ANSI_NATIONAL_MASK;
863     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_national_indicator
864                                              : hf_sccp_calling_national_indicator,
865                         tvb, 0, ADDRESS_INDICATOR_LENGTH, national);
866   }
867
868   routing_ind = tvb_get_guint8(tvb, 0) & ROUTING_INDICATOR_MASK;
869   proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_routing_indicator
870                                            : hf_sccp_calling_routing_indicator,
871                       tvb, 0, ADDRESS_INDICATOR_LENGTH, routing_ind);
872
873   gti = tvb_get_guint8(tvb, 0) & GTI_MASK;
874
875   if (mtp3_standard == ITU_STANDARD || national == 0) {
876
877     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_global_title_indicator
878                                              : hf_sccp_called_itu_global_title_indicator,
879                         tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
880
881     ssni = tvb_get_guint8(tvb, 0) & ITU_SSN_INDICATOR_MASK;
882     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_ssn_indicator
883                                              : hf_sccp_calling_itu_ssn_indicator,
884                         tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
885
886     pci = tvb_get_guint8(tvb, 0) & ITU_PC_INDICATOR_MASK;
887     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_point_code_indicator
888                                              : hf_sccp_calling_itu_point_code_indicator,
889                         tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
890
891     offset = ADDRESS_INDICATOR_LENGTH;
892
893     /* Dissect PC (if present) */
894     if (pci) {
895       dpc = tvb_get_letohs(tvb, offset) & ITU_PC_MASK;
896       proto_tree_add_uint(call_tree, called ? hf_sccp_called_itu_pc
897                                             : hf_sccp_calling_itu_pc,
898                           tvb, offset, ITU_PC_LENGTH, dpc);
899       offset += ITU_PC_LENGTH;
900     }
901
902     /* Dissect SSN (if present) */
903     if (ssni) {
904       ssn = tvb_get_guint8(tvb, offset);
905       if (called) {
906               called_ssn = ssn;
907       }
908       else {
909               calling_ssn = ssn;
910       }
911
912       proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
913                                             : hf_sccp_calling_ssn,
914                           tvb, offset, ADDRESS_SSN_LENGTH, ssn);
915       proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
916                                  ADDRESS_SSN_LENGTH, ssn);
917       offset += ADDRESS_SSN_LENGTH;
918     }
919
920     if (!tree)
921       return;   /* got SSN, that's all we need here... */
922
923     /* Dissect GT (if present) */
924     if (gti != AI_GTI_NO_GT) {
925       gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
926                               (length - offset));
927       dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
928                                 called);
929     }
930
931   } else if (mtp3_standard == ANSI_STANDARD) {
932
933     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_global_title_indicator
934                                              : hf_sccp_calling_ansi_global_title_indicator,
935                         tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
936
937     pci = tvb_get_guint8(tvb, 0) & ANSI_PC_INDICATOR_MASK;
938     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_point_code_indicator
939                                              : hf_sccp_calling_ansi_point_code_indicator,
940                         tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
941
942     ssni = tvb_get_guint8(tvb, 0) & ANSI_SSN_INDICATOR_MASK;
943     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator
944                                              : hf_sccp_calling_ansi_ssn_indicator,
945                         tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
946
947     offset = ADDRESS_INDICATOR_LENGTH;
948
949     /* Dissect SSN (if present) */
950     if (ssni) {
951       ssn = tvb_get_guint8(tvb, offset);
952       if (called) {
953               called_ssn = ssn;
954       }
955       else {
956               calling_ssn = ssn;
957       }
958
959       proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
960                                             : hf_sccp_calling_ssn,
961                           tvb, offset, ADDRESS_SSN_LENGTH, ssn);
962       proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
963                                  ADDRESS_SSN_LENGTH, ssn);
964       offset += ADDRESS_SSN_LENGTH;
965     }
966
967     if (!tree)
968       return;   /* got SSN, that's all we need here... */
969
970     /* Dissect PC (if present) */
971     if (pci) {
972       /* create the DPC tree; modified from that in packet-mtp3.c */
973       dpc = tvb_get_ntoh24(tvb, offset);
974       snprintf(pc, sizeof(pc), "%d-%d-%d", (dpc & ANSI_NETWORK_MASK),
975                                            ((dpc & ANSI_CLUSTER_MASK) >> 8),
976                                            ((dpc & ANSI_MEMBER_MASK) >> 16));
977
978       call_pc_item = proto_tree_add_string_format(call_tree,
979                                                   called ? hf_sccp_called_ansi_pc
980                                                          : hf_sccp_calling_ansi_pc,
981                                                   tvb, offset, ANSI_PC_LENGTH,
982                                                   pc, "PC (%s)", pc);
983
984       call_pc_tree = proto_item_add_subtree(call_pc_item,
985                                               called ? ett_sccp_called_pc
986                                                      : ett_sccp_calling_pc);
987
988       proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_member
989                                                : hf_sccp_calling_pc_member,
990                           tvb, offset, ANSI_NCM_LENGTH, dpc);
991       offset += ANSI_NCM_LENGTH;
992       proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_cluster
993                                                : hf_sccp_calling_pc_cluster,
994                           tvb, offset, ANSI_NCM_LENGTH, dpc);
995       offset += ANSI_NCM_LENGTH;
996       proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_network
997                                                : hf_sccp_calling_pc_network,
998                           tvb, offset, ANSI_NCM_LENGTH, dpc);
999       offset += ANSI_NCM_LENGTH;
1000     }
1001
1002     /* Dissect GT (if present) */
1003     if (gti != AI_GTI_NO_GT) {
1004       gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
1005                               (length - offset));
1006       dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
1007                                 called);
1008     }
1009
1010   }
1011
1012 }
1013
1014 static void
1015 dissect_sccp_called_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1016 {
1017   dissect_sccp_called_calling_param(tvb, tree, length, TRUE);
1018 }
1019
1020 static void
1021 dissect_sccp_calling_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1022 {
1023   dissect_sccp_called_calling_param(tvb, tree, length, FALSE);
1024 }
1025
1026 static void
1027 dissect_sccp_class_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1028 {
1029   guint8 class, handling;
1030
1031   class = tvb_get_guint8(tvb, 0) & CLASS_CLASS_MASK;
1032   handling = tvb_get_guint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK;
1033
1034   proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, class);
1035
1036   if (class == 0 || class == 1)
1037     proto_tree_add_uint(tree, hf_sccp_handling, tvb, 0, length, handling);
1038 }
1039
1040 static void
1041 dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1042 {
1043   guint8 more;
1044
1045   more = tvb_get_guint8(tvb, 0) & SEGMENTING_REASSEMBLING_MASK;
1046   proto_tree_add_uint(tree, hf_sccp_more, tvb, 0, length, more);
1047 }
1048
1049 static void
1050 dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1051 {
1052   guint8 rsn;
1053
1054   rsn = tvb_get_guint8(tvb, 0) >> 1;
1055   proto_tree_add_uint(tree, hf_sccp_rsn, tvb, 0, length, rsn);
1056 }
1057
1058 static void
1059 dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1060 {
1061   guint8 rsn, ssn, more;
1062   proto_item *param_item;
1063   proto_tree *param_tree;
1064
1065   ssn = tvb_get_guint8(tvb, 0) >> 1;
1066   rsn = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) >> 1;
1067   more = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) & SEQUENCING_SEGMENTING_MORE_MASK;
1068
1069   param_item = proto_tree_add_text(tree, tvb, 0, length,
1070                                    val_to_str(PARAMETER_SEQUENCING_SEGMENTING,
1071                                               sccp_parameter_values, "Unknown"));
1072   param_tree = proto_item_add_subtree(param_item,
1073                                       ett_sccp_sequencing_segmenting);
1074
1075   proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_ssn, tvb, 0,
1076                       SEQUENCING_SEGMENTING_SSN_LENGTH, ssn);
1077   proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_rsn, tvb,
1078                       SEQUENCING_SEGMENTING_SSN_LENGTH,
1079                       SEQUENCING_SEGMENTING_RSN_LENGTH, rsn);
1080   proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_more, tvb,
1081                       SEQUENCING_SEGMENTING_SSN_LENGTH,
1082                       SEQUENCING_SEGMENTING_RSN_LENGTH, more);
1083 }
1084
1085 static void
1086 dissect_sccp_credit_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1087 {
1088   guint8 credit;
1089
1090   credit = tvb_get_guint8(tvb, 0);
1091   proto_tree_add_uint(tree, hf_sccp_credit, tvb, 0, length, credit);
1092 }
1093
1094 static void
1095 dissect_sccp_release_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1096 {
1097   guint8 cause;
1098
1099   cause = tvb_get_guint8(tvb, 0);
1100   proto_tree_add_uint(tree, hf_sccp_release_cause, tvb, 0, length, cause);
1101 }
1102
1103 static void
1104 dissect_sccp_return_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1105 {
1106   guint8 cause;
1107
1108   cause = tvb_get_guint8(tvb, 0);
1109   proto_tree_add_uint(tree, hf_sccp_return_cause, tvb, 0, length, cause);
1110 }
1111
1112 static void
1113 dissect_sccp_reset_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1114 {
1115   guint8 cause;
1116
1117   cause = tvb_get_guint8(tvb, 0);
1118   proto_tree_add_uint(tree, hf_sccp_reset_cause, tvb, 0, length, cause);
1119 }
1120
1121 static void
1122 dissect_sccp_error_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1123 {
1124   guint8 cause;
1125
1126   cause = tvb_get_guint8(tvb, 0);
1127   proto_tree_add_uint(tree, hf_sccp_error_cause, tvb, 0, length, cause);
1128 }
1129
1130 static void
1131 dissect_sccp_refusal_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1132 {
1133   guint8 cause;
1134
1135   cause = tvb_get_guint8(tvb, 0);
1136   proto_tree_add_uint(tree, hf_sccp_refusal_cause, tvb, 0, length, cause);
1137 }
1138
1139 /* This function is used for both data and long data (ITU only) parameters */
1140 static void
1141 dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo,
1142                         proto_tree *sccp_tree, proto_tree *tree)
1143 {
1144
1145   /* Try subdissectors (if we found a valid SSN on the current message) */
1146   if ((called_ssn != INVALID_SSN &&
1147        dissector_try_port(sccp_ssn_dissector_table, called_ssn, tvb, pinfo,
1148                           tree)) ||
1149       (calling_ssn != INVALID_SSN &&
1150        dissector_try_port(sccp_ssn_dissector_table, calling_ssn, tvb, pinfo,
1151                           tree)))
1152     return;
1153
1154     /* No sub-dissection occured, treat it as raw data */
1155     call_dissector(data_handle, tvb, pinfo, sccp_tree);
1156 }
1157
1158 static void
1159 dissect_sccp_segmentation_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1160 {
1161   guint8 first, class, remaining;
1162   guint32 slr;
1163   proto_item *param_item;
1164   proto_tree *param_tree;
1165
1166   first = tvb_get_guint8(tvb, 0) & SEGMENTATION_FIRST_SEGMENT_MASK;
1167   class = tvb_get_guint8(tvb, 0) & SEGMENTATION_CLASS_MASK;
1168   remaining = tvb_get_guint8(tvb, 0) & SEGMENTATION_REMAINING_MASK;
1169
1170   slr = tvb_get_ntoh24(tvb, 1);
1171
1172   param_item = proto_tree_add_text(tree, tvb, 0, length,
1173                                    val_to_str(PARAMETER_SEGMENTATION,
1174                                               sccp_parameter_values, "Unknown"));
1175   param_tree = proto_item_add_subtree(param_item, ett_sccp_segmentation);
1176
1177   proto_tree_add_uint(param_tree, hf_sccp_segmentation_first, tvb, 0, length,
1178                       first);
1179   proto_tree_add_uint(param_tree, hf_sccp_segmentation_class, tvb, 0, length,
1180                       class);
1181   proto_tree_add_uint(param_tree, hf_sccp_segmentation_remaining, tvb, 0,
1182                       length, remaining);
1183   proto_tree_add_uint(param_tree, hf_sccp_segmentation_slr, tvb, 1, length,
1184                       slr);
1185 }
1186
1187 static void
1188 dissect_sccp_hop_counter_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1189 {
1190   guint8 hops;
1191
1192   hops = tvb_get_guint8(tvb, 0);
1193   proto_tree_add_uint(tree, hf_sccp_hop_counter, tvb, 0, length, hops);
1194 }
1195
1196 static void
1197 dissect_sccp_importance_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1198 {
1199   guint8 importance;
1200
1201   importance = tvb_get_guint8(tvb, 0) & IMPORTANCE_IMPORTANCE_MASK;
1202   proto_tree_add_uint(tree, hf_sccp_importance, tvb, 0, length, importance);
1203 }
1204
1205 static void
1206 dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1207 {
1208   guint8 mi, iri, ti, network, netspec;
1209   guint8 offset = 0;
1210   proto_item *param_item;
1211   proto_tree *param_tree;
1212
1213   /* Create a subtree for ISNI Routing Control */
1214   param_item = proto_tree_add_text(tree, tvb, offset, ANSI_ISNI_ROUTING_CONTROL_LENGTH,
1215                                    "ISNI Routing Control");
1216   param_tree = proto_item_add_subtree(param_item,
1217                                       ett_sccp_ansi_isni_routing_control);
1218
1219   mi = tvb_get_guint8(tvb, offset) & ANSI_ISNI_MI_MASK;
1220   proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_mi, tvb, offset,
1221                       ANSI_ISNI_ROUTING_CONTROL_LENGTH, mi);
1222
1223   iri = tvb_get_guint8(tvb, offset) & ANSI_ISNI_IRI_MASK;
1224   proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_iri, tvb, offset,
1225                       ANSI_ISNI_ROUTING_CONTROL_LENGTH, iri);
1226
1227   ti = tvb_get_guint8(tvb, offset) & ANSI_ISNI_TI_MASK;
1228   proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_ti, tvb, offset,
1229                       ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
1230
1231   offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
1232
1233   if ((ti >> ANSI_ISNI_TI_SHIFT) == ANSI_ISNI_TYPE_1) {
1234     netspec = tvb_get_guint8(tvb, offset) & ANSI_ISNI_NETSPEC_MASK;
1235     proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_netspec, tvb, offset,
1236                         ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
1237     offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
1238   }
1239
1240   while (offset < length) {
1241
1242     network = tvb_get_guint8(tvb, offset);
1243     proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
1244                         "Network ID network: %d", network);
1245     offset++;
1246
1247     network = tvb_get_guint8(tvb, offset);
1248     proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
1249                         "Network ID cluster: %d", network);
1250     offset++;
1251   }
1252
1253 }
1254
1255 /*  FUNCTION dissect_sccp_parameter():
1256  *  Dissect a parameter given its type, offset into tvb, and length.
1257  */
1258 static guint16
1259 dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
1260                        proto_tree *tree, guint8 parameter_type, guint8 offset,
1261                        guint16 parameter_length)
1262 {
1263     tvbuff_t *parameter_tvb;
1264
1265     switch (parameter_type) {
1266     case PARAMETER_CALLED_PARTY_ADDRESS:
1267     case PARAMETER_CALLING_PARTY_ADDRESS:
1268     case PARAMETER_DATA:
1269     case PARAMETER_LONG_DATA:
1270       /*  These parameters must be dissected even if !sccp_tree (so that
1271        *  subdissectors can be called).
1272        */
1273       break;
1274
1275     default:
1276       if (!sccp_tree)
1277         return(parameter_length);
1278
1279     }
1280
1281     parameter_tvb = tvb_new_subset(tvb, offset, parameter_length, parameter_length);
1282
1283     switch (parameter_type) {
1284
1285     case PARAMETER_END_OF_OPTIONAL_PARAMETERS:
1286       proto_tree_add_text(sccp_tree, tvb, offset, parameter_length,
1287                           "End of Optional");
1288       break;
1289
1290     case PARAMETER_DESTINATION_LOCAL_REFERENCE:
1291       dissect_sccp_dlr_param(parameter_tvb, sccp_tree, parameter_length);
1292       break;
1293
1294     case PARAMETER_SOURCE_LOCAL_REFERENCE:
1295       dissect_sccp_slr_param(parameter_tvb, sccp_tree, parameter_length);
1296       break;
1297
1298     case PARAMETER_CALLED_PARTY_ADDRESS:
1299       dissect_sccp_called_param(parameter_tvb, sccp_tree, parameter_length);
1300       break;
1301
1302     case PARAMETER_CALLING_PARTY_ADDRESS:
1303       dissect_sccp_calling_param(parameter_tvb, sccp_tree, parameter_length);
1304       break;
1305
1306     case PARAMETER_CLASS:
1307       dissect_sccp_class_param(parameter_tvb, sccp_tree, parameter_length);
1308       break;
1309
1310     case PARAMETER_SEGMENTING_REASSEMBLING:
1311       dissect_sccp_segmenting_reassembling_param(parameter_tvb, sccp_tree,
1312                                                    parameter_length);
1313       break;
1314
1315     case PARAMETER_RECEIVE_SEQUENCE_NUMBER:
1316       dissect_sccp_receive_sequence_number_param(parameter_tvb, sccp_tree,
1317                                                  parameter_length);
1318       break;
1319
1320     case PARAMETER_SEQUENCING_SEGMENTING:
1321       dissect_sccp_sequencing_segmenting_param(parameter_tvb, sccp_tree,
1322                                                parameter_length);
1323       break;
1324
1325     case PARAMETER_CREDIT:
1326       dissect_sccp_credit_param(parameter_tvb, sccp_tree, parameter_length);
1327       break;
1328
1329     case PARAMETER_RELEASE_CAUSE:
1330       dissect_sccp_release_cause_param(parameter_tvb, sccp_tree, parameter_length);
1331       break;
1332
1333     case PARAMETER_RETURN_CAUSE:
1334       dissect_sccp_return_cause_param(parameter_tvb, sccp_tree, parameter_length);
1335       break;
1336
1337     case PARAMETER_RESET_CAUSE:
1338       dissect_sccp_reset_cause_param(parameter_tvb, sccp_tree, parameter_length);
1339       break;
1340
1341     case PARAMETER_ERROR_CAUSE:
1342       dissect_sccp_error_cause_param(parameter_tvb, sccp_tree, parameter_length);
1343       break;
1344
1345     case PARAMETER_REFUSAL_CAUSE:
1346       dissect_sccp_refusal_cause_param(parameter_tvb, sccp_tree, parameter_length);
1347       break;
1348
1349     case PARAMETER_DATA:
1350       dissect_sccp_data_param(parameter_tvb, pinfo, sccp_tree, tree);
1351
1352       /* TODO? Re-adjust length of SCCP item since it may be sub-dissected */
1353       /* sccp_length = proto_item_get_len(sccp_item);
1354        * sccp_length -= parameter_length;
1355        * proto_item_set_len(sccp_item, sccp_length);
1356        */
1357       break;
1358
1359     case PARAMETER_SEGMENTATION:
1360       dissect_sccp_segmentation_param(parameter_tvb, sccp_tree, parameter_length);
1361       break;
1362
1363     case PARAMETER_HOP_COUNTER:
1364       dissect_sccp_hop_counter_param(parameter_tvb, sccp_tree, parameter_length);
1365       break;
1366
1367     case PARAMETER_IMPORTANCE:
1368       if (mtp3_standard == ITU_STANDARD)
1369         dissect_sccp_importance_param(parameter_tvb, sccp_tree, parameter_length);
1370       else
1371         dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1372                                    parameter_length);
1373       break;
1374
1375     case PARAMETER_LONG_DATA:
1376       if (mtp3_standard == ITU_STANDARD)
1377         dissect_sccp_data_param(parameter_tvb, pinfo, sccp_tree, tree);
1378       else
1379         dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1380                                    parameter_length);
1381       break;
1382
1383     case PARAMETER_ISNI:
1384       if (mtp3_standard == ANSI_STANDARD)
1385         dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
1386       else
1387         dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1388                                    parameter_length);
1389       break;
1390
1391     default:
1392       dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1393                                  parameter_length);
1394       break;
1395     }
1396
1397     return(parameter_length);
1398 }
1399
1400 /*  FUNCTION dissect_sccp_variable_parameter():
1401  *  Dissect a variable parameter given its type and offset into tvb.  Length
1402  *  of the parameter is gotten from tvb[0].
1403  *  Length returned is sum of (length + parameter).
1404  */
1405 static guint16
1406 dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo,
1407                                 proto_tree *sccp_tree, proto_tree *tree,
1408                                 guint8 parameter_type, guint8 offset)
1409 {
1410   guint16 parameter_length;
1411   guint8 length_length;
1412
1413   if (parameter_type != PARAMETER_LONG_DATA)
1414   {
1415     parameter_length = tvb_get_guint8(tvb, offset);
1416     length_length = PARAMETER_LENGTH_LENGTH;
1417   }
1418   else
1419   {
1420     /* Long data parameter has 16 bit length */
1421     parameter_length = tvb_get_ntohs(tvb, offset);
1422     length_length = PARAMETER_LONG_DATA_LENGTH_LENGTH;
1423   }
1424
1425 /*  TODO? I find this annoying, but it could possibly useful for debugging.
1426  *  Make it a preference?
1427  * if (sccp_tree)
1428  *   proto_tree_add_text(sccp_tree, tvb, offset, length_length,
1429  *                      "%s length: %d",
1430  *                      val_to_str(parameter_type, sccp_parameter_values,
1431  *                                 "Unknown"),
1432  *                      parameter_length);
1433  */
1434
1435   offset += length_length;
1436
1437   dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
1438                          parameter_length);
1439
1440   return(parameter_length + length_length);
1441 }
1442
1443 /*  FUNCTION dissect_sccp_optional_parameters():
1444  *  Dissect all the optional parameters given the start of the optional
1445  *  parameters into tvb.  Parameter types and lengths are read from tvb.
1446  */
1447 static void
1448 dissect_sccp_optional_parameters(tvbuff_t *tvb, packet_info *pinfo,
1449                                  proto_tree *sccp_tree, proto_tree *tree,
1450                                  guint8 offset)
1451 {
1452   guint8 parameter_type;
1453
1454   while ((parameter_type = tvb_get_guint8(tvb, offset)) !=
1455          PARAMETER_END_OF_OPTIONAL_PARAMETERS) {
1456
1457     offset += PARAMETER_TYPE_LENGTH;
1458     offset += dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1459                                               parameter_type, offset);
1460   }
1461
1462   /* Process end of optional parameters */
1463   dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
1464                          END_OF_OPTIONAL_PARAMETERS_LENGTH);
1465
1466 }
1467
1468
1469 static void
1470 dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
1471                      proto_tree *tree)
1472 {
1473   guint8 message_type;
1474   guint8 variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
1475   guint8 optional_pointer = 0;
1476   guint8 offset = 0;
1477
1478 /* Macro for getting pointer to mandatory variable parameters */
1479 #define VARIABLE_POINTER(var, hf_var) \
1480     var = tvb_get_guint8(tvb, offset); \
1481     proto_tree_add_uint(sccp_tree, hf_var, tvb, \
1482                         offset, POINTER_LENGTH, var); \
1483     var += offset; \
1484     offset += POINTER_LENGTH;
1485
1486 /* Macro for getting pointer to optional parameters */
1487 #define OPTIONAL_POINTER \
1488     optional_pointer = tvb_get_guint8(tvb, offset); \
1489     proto_tree_add_uint(sccp_tree, hf_sccp_optional_pointer, tvb, \
1490                         offset, POINTER_LENGTH, optional_pointer); \
1491     optional_pointer += offset; \
1492     offset += POINTER_LENGTH;
1493
1494   /* Extract the message type;  all other processing is based on this */
1495   message_type   = tvb_get_guint8(tvb, MESSAGE_TYPE_OFFSET);
1496   offset = MESSAGE_TYPE_LENGTH;
1497
1498   if (check_col(pinfo->cinfo, COL_INFO)) {
1499     col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
1500                     val_to_str(message_type, sccp_message_type_acro_values, "Unknown"));
1501   };
1502
1503   if (sccp_tree) {
1504     /* add the message type to the protocol tree */
1505     proto_tree_add_uint(sccp_tree, hf_sccp_message_type, tvb,
1506                         MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, message_type);
1507
1508   };
1509
1510   /* Starting a new message dissection; clear the global SSN values */
1511   called_ssn = INVALID_SSN;
1512   calling_ssn = INVALID_SSN;
1513
1514   switch(message_type) {
1515   case MESSAGE_TYPE_CR:
1516     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1517                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1518                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1519     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1520                                      PARAMETER_CLASS, offset,
1521                                      PROTOCOL_CLASS_LENGTH);
1522
1523     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
1524     OPTIONAL_POINTER
1525
1526     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1527                                     PARAMETER_CALLED_PARTY_ADDRESS,
1528                                     variable_pointer1);
1529     break;
1530
1531   case MESSAGE_TYPE_CC:
1532     /*  TODO: connection has been established;  theoretically we could keep
1533      *  keep track of the SLR/DLR with the called/calling from the CR and
1534      *  track the connection (e.g., on subsequent messages regarding this
1535      *  SLR we could set the global vars "call*_ssn" so data could get
1536      *  sub-dissected).
1537      */
1538     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1539                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1540                                      offset,
1541                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1542     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1543                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1544                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1545     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1546                                      PARAMETER_CLASS, offset,
1547                                      PROTOCOL_CLASS_LENGTH);
1548     OPTIONAL_POINTER
1549     break;
1550
1551   case MESSAGE_TYPE_CREF:
1552     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1553                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1554                                      offset,
1555                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1556     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1557                                      PARAMETER_REFUSAL_CAUSE, offset,
1558                                      REFUSAL_CAUSE_LENGTH);
1559     OPTIONAL_POINTER
1560     break;
1561
1562   case MESSAGE_TYPE_RLSD:
1563     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1564                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1565                                      offset,
1566                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1567     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1568                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1569                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1570     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1571                                      PARAMETER_RELEASE_CAUSE, offset,
1572                                      RELEASE_CAUSE_LENGTH);
1573
1574     OPTIONAL_POINTER
1575     break;
1576
1577   case MESSAGE_TYPE_RLC:
1578     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1579                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1580                                      offset,
1581                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1582     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1583                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1584                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1585     break;
1586
1587   case MESSAGE_TYPE_DT1:
1588     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1589                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1590                                      offset,
1591                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1592     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1593                                      PARAMETER_SEGMENTING_REASSEMBLING,
1594                                      offset, SEGMENTING_REASSEMBLING_LENGTH);
1595
1596     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
1597     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1598                                     variable_pointer1);
1599     break;
1600
1601   case MESSAGE_TYPE_DT2:
1602     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1603                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1604                                      offset,
1605                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1606     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1607                                      PARAMETER_SEQUENCING_SEGMENTING, offset,
1608                                      SEQUENCING_SEGMENTING_LENGTH);
1609     break;
1610
1611   case MESSAGE_TYPE_AK:
1612     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1613                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1614                                      offset,
1615                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1616     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1617                                      PARAMETER_RECEIVE_SEQUENCE_NUMBER,
1618                                      offset, RECEIVE_SEQUENCE_NUMBER_LENGTH);
1619     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1620                                      PARAMETER_CREDIT, offset, CREDIT_LENGTH);
1621     break;
1622
1623   case MESSAGE_TYPE_UDT:
1624     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1625                                      PARAMETER_CLASS, offset,
1626                                      PROTOCOL_CLASS_LENGTH);
1627     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
1628     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
1629     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
1630
1631     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1632                                     PARAMETER_CALLED_PARTY_ADDRESS,
1633                                     variable_pointer1);
1634     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1635                                     PARAMETER_CALLING_PARTY_ADDRESS,
1636                                     variable_pointer2);
1637     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1638                                     variable_pointer3);
1639     break;
1640
1641   case MESSAGE_TYPE_UDTS:
1642     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1643                                      PARAMETER_RETURN_CAUSE, offset,
1644                                      RETURN_CAUSE_LENGTH);
1645
1646     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
1647     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
1648     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
1649
1650     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1651                                     PARAMETER_CALLED_PARTY_ADDRESS,
1652                                     variable_pointer1);
1653
1654     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1655                                     PARAMETER_CALLING_PARTY_ADDRESS,
1656                                     variable_pointer2);
1657
1658     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1659                                     variable_pointer3);
1660     break;
1661
1662   case MESSAGE_TYPE_ED:
1663     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1664                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1665                                      offset,
1666                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1667
1668     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
1669     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1670                                     variable_pointer1);
1671     break;
1672
1673   case MESSAGE_TYPE_EA:
1674     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1675                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1676                                      offset,
1677                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1678     break;
1679
1680   case MESSAGE_TYPE_RSR:
1681     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1682                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1683                                      offset,
1684                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1685     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1686                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1687                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1688     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1689                                      PARAMETER_RESET_CAUSE, offset,
1690                                      RESET_CAUSE_LENGTH);
1691     break;
1692
1693   case MESSAGE_TYPE_RSC:
1694     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1695                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1696                                      offset,
1697                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1698     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1699                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1700                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1701     break;
1702
1703   case MESSAGE_TYPE_ERR:
1704     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1705                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1706                                      offset,
1707                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1708     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1709                                      PARAMETER_ERROR_CAUSE, offset,
1710                                      ERROR_CAUSE_LENGTH);
1711     break;
1712
1713   case MESSAGE_TYPE_IT:
1714     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1715                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1716                                      offset,
1717                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1718     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1719                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1720                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1721     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1722                                      PARAMETER_CLASS, offset,
1723                                      PROTOCOL_CLASS_LENGTH);
1724     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1725                                      PARAMETER_SEQUENCING_SEGMENTING,
1726                                      offset, SEQUENCING_SEGMENTING_LENGTH);
1727     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1728                                      PARAMETER_CREDIT, offset, CREDIT_LENGTH);
1729     break;
1730
1731   case MESSAGE_TYPE_XUDT:
1732     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1733                                      PARAMETER_CLASS, offset,
1734                                      PROTOCOL_CLASS_LENGTH);
1735     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1736                                      PARAMETER_HOP_COUNTER, offset,
1737                                      HOP_COUNTER_LENGTH);
1738
1739     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
1740     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
1741     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
1742     OPTIONAL_POINTER
1743
1744     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1745                                     PARAMETER_CALLED_PARTY_ADDRESS,
1746                                     variable_pointer1);
1747     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1748                                     PARAMETER_CALLING_PARTY_ADDRESS,
1749                                     variable_pointer2);
1750     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1751                                     variable_pointer3);
1752     break;
1753
1754   case MESSAGE_TYPE_XUDTS:
1755     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1756                                      PARAMETER_RETURN_CAUSE, offset,
1757                                      RETURN_CAUSE_LENGTH);
1758     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1759                                      PARAMETER_HOP_COUNTER, offset,
1760                                      HOP_COUNTER_LENGTH);
1761
1762     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
1763     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
1764     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
1765     OPTIONAL_POINTER
1766
1767     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1768                                     PARAMETER_CALLED_PARTY_ADDRESS,
1769                                     variable_pointer1);
1770     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1771                                     PARAMETER_CALLING_PARTY_ADDRESS,
1772                                     variable_pointer2);
1773     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1774                                     variable_pointer3);
1775     break;
1776
1777   case MESSAGE_TYPE_LUDT:
1778     if (mtp3_standard == ITU_STANDARD)
1779     {
1780       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1781                                        PARAMETER_CLASS, offset,
1782                                        PROTOCOL_CLASS_LENGTH);
1783       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1784                                        PARAMETER_HOP_COUNTER, offset,
1785                                        HOP_COUNTER_LENGTH);
1786
1787       VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
1788       VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
1789       VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
1790       OPTIONAL_POINTER
1791
1792       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1793                                       PARAMETER_CALLED_PARTY_ADDRESS,
1794                                       variable_pointer1);
1795       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1796                                       PARAMETER_CALLING_PARTY_ADDRESS,
1797                                       variable_pointer2);
1798       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1799                                       PARAMETER_LONG_DATA, variable_pointer3);
1800     } else
1801       dissect_sccp_unknown_message(tvb, sccp_tree);
1802     break;
1803
1804   case MESSAGE_TYPE_LUDTS:
1805     if (mtp3_standard == ITU_STANDARD)
1806     {
1807       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1808                                        PARAMETER_RETURN_CAUSE, offset,
1809                                        RETURN_CAUSE_LENGTH);
1810       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1811                                        PARAMETER_HOP_COUNTER, offset,
1812                                        HOP_COUNTER_LENGTH);
1813
1814       VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
1815       VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
1816       VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
1817       OPTIONAL_POINTER
1818
1819       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1820                                       PARAMETER_CALLED_PARTY_ADDRESS,
1821                                       variable_pointer1);
1822       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1823                                       PARAMETER_CALLING_PARTY_ADDRESS,
1824                                       variable_pointer2);
1825       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1826                                       PARAMETER_LONG_DATA, variable_pointer3);
1827     } else
1828       dissect_sccp_unknown_message(tvb, sccp_tree);
1829     break;
1830
1831   default:
1832     dissect_sccp_unknown_message(tvb, sccp_tree);
1833   }
1834
1835   if (optional_pointer)
1836     dissect_sccp_optional_parameters(tvb, pinfo, sccp_tree, tree,
1837                                      optional_pointer);
1838
1839 }
1840
1841 static void
1842 dissect_sccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1843 {
1844   proto_item *sccp_item;
1845   proto_tree *sccp_tree = NULL;
1846
1847   /* Make entry in the Protocol column on summary display */
1848   if (check_col(pinfo->cinfo, COL_PROTOCOL))
1849     col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP");
1850
1851   /* In the interest of speed, if "tree" is NULL, don't do any work not
1852      necessary to generate protocol tree items. */
1853   if (tree) {
1854     /* create the sccp protocol tree */
1855     sccp_item = proto_tree_add_item(tree, proto_sccp, tvb, 0, -1, FALSE);
1856     sccp_tree = proto_item_add_subtree(sccp_item, ett_sccp);
1857   }
1858
1859   /* dissect the message */
1860   dissect_sccp_message(tvb, pinfo, sccp_tree, tree);
1861 }
1862
1863 /* Register the protocol with Ethereal */
1864 void
1865 proto_register_sccp(void)
1866 {
1867   /* Setup list of header fields */
1868   static hf_register_info hf[] = {
1869     { &hf_sccp_message_type,
1870       { "Message Type", "sccp.message_type",
1871         FT_UINT8, BASE_HEX, VALS(sccp_message_type_values), 0x0,
1872         "", HFILL}},
1873     { &hf_sccp_variable_pointer1,
1874       { "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1",
1875         FT_UINT8, BASE_DEC, NULL, 0x0,
1876         "", HFILL}},
1877     { &hf_sccp_variable_pointer2,
1878       { "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2",
1879         FT_UINT8, BASE_DEC, NULL, 0x0,
1880         "", HFILL}},
1881     { &hf_sccp_variable_pointer3,
1882       { "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3",
1883         FT_UINT8, BASE_DEC, NULL, 0x0,
1884         "", HFILL}},
1885     { &hf_sccp_optional_pointer,
1886       { "Pointer to Optional parameter", "sccp.optional_pointer",
1887         FT_UINT8, BASE_DEC, NULL, 0x0,
1888         "", HFILL}},
1889     { &hf_sccp_ssn,
1890       { "Called or Calling SubSystem Number", "sccp.ssn",
1891         FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
1892         "", HFILL}},
1893     { &hf_sccp_gt_digits,
1894       { "Called or Calling GT Digits",
1895         "sccp.digits",
1896         FT_STRING, BASE_NONE, NULL, 0x0,
1897         "", HFILL }},
1898
1899     { &hf_sccp_called_national_indicator,
1900       { "National Indicator", "sccp.called.ni",
1901         FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
1902         "", HFILL}},
1903     { &hf_sccp_called_routing_indicator,
1904       { "Routing Indicator", "sccp.called.ri",
1905         FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
1906         "", HFILL}},
1907     { &hf_sccp_called_itu_global_title_indicator,
1908       { "Global Title Indicator", "sccp.called.gti",
1909         FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
1910         "", HFILL}},
1911     { &hf_sccp_called_ansi_global_title_indicator,
1912       { "Global Title Indicator", "sccp.called.gti",
1913         FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
1914         "", HFILL}},
1915     { &hf_sccp_called_itu_ssn_indicator,
1916       { "SubSystem Number Indicator", "sccp.called.ssni",
1917         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
1918         "", HFILL}},
1919     { &hf_sccp_called_itu_point_code_indicator,
1920       { "Point Code Indicator", "sccp.called.pci",
1921         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
1922         "", HFILL}},
1923     { &hf_sccp_called_ansi_ssn_indicator,
1924       { "SubSystem Number Indicator", "sccp.called.ssni",
1925         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
1926         "", HFILL}},
1927     { &hf_sccp_called_ansi_point_code_indicator,
1928       { "Point Code Indicator", "sccp.called.pci",
1929         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
1930         "", HFILL}},
1931     { &hf_sccp_called_ssn,
1932       { "SubSystem Number", "sccp.called.ssn",
1933         FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
1934         "", HFILL}},
1935     { &hf_sccp_called_itu_pc,
1936       { "PC", "sccp.called.pc",
1937         FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
1938         "", HFILL}},
1939     { &hf_sccp_called_ansi_pc,
1940       { "PC", "sccp.called.ansi_pc",
1941         FT_STRING, BASE_NONE, NULL, 0x0,
1942         "", HFILL}},
1943     { &hf_sccp_called_pc_network,
1944       { "PC Network",
1945         "sccp.called.network",
1946         FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
1947         "", HFILL }},
1948     { &hf_sccp_called_pc_cluster,
1949       { "PC Cluster",
1950         "sccp.called.cluster",
1951         FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
1952         "", HFILL }},
1953     { &hf_sccp_called_pc_member,
1954       { "PC Member",
1955         "sccp.called.member",
1956         FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
1957         "", HFILL }},
1958     { &hf_sccp_called_gt_nai,
1959       { "Nature of Address Indicator",
1960         "sccp.called.nai",
1961         FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
1962         "", HFILL }},
1963     { &hf_sccp_called_gt_oe,
1964       { "Odd/Even Indicator",
1965         "sccp.called.oe",
1966         FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
1967         "", HFILL }},
1968     { &hf_sccp_called_gt_tt,
1969       { "Translation Type",
1970         "sccp.called.tt",
1971         FT_UINT8, BASE_HEX, NULL, 0x0,
1972         "", HFILL }},
1973     { &hf_sccp_called_gt_np,
1974       { "Numbering Plan",
1975         "sccp.called.np",
1976         FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
1977         "", HFILL }},
1978     { &hf_sccp_called_gt_es,
1979       { "Encoding Scheme",
1980         "sccp.called.es",
1981         FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
1982         "", HFILL }},
1983     { &hf_sccp_called_gt_digits,
1984       { "GT Digits",
1985         "sccp.called.digits",
1986         FT_STRING, BASE_NONE, NULL, 0x0,
1987         "", HFILL }},
1988
1989     { &hf_sccp_calling_national_indicator,
1990       { "National Indicator", "sccp.calling.ni",
1991         FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
1992         "", HFILL}},
1993     { &hf_sccp_calling_routing_indicator,
1994       { "Routing Indicator", "sccp.calling.ri",
1995         FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
1996         "", HFILL}},
1997     { &hf_sccp_calling_itu_global_title_indicator,
1998       { "Global Title Indicator", "sccp.calling.gti",
1999         FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
2000         "", HFILL}},
2001     { &hf_sccp_calling_ansi_global_title_indicator,
2002       { "Global Title Indicator", "sccp.calling.gti",
2003         FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
2004         "", HFILL}},
2005     { &hf_sccp_calling_itu_ssn_indicator,
2006       { "SubSystem Number Indicator", "sccp.calling.ssni",
2007         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
2008         "", HFILL}},
2009     { &hf_sccp_calling_itu_point_code_indicator,
2010       { "Point Code Indicator", "sccp.calling.pci",
2011         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
2012         "", HFILL}},
2013     { &hf_sccp_calling_ansi_ssn_indicator,
2014       { "SubSystem Number Indicator", "sccp.calling.ssni",
2015         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
2016         "", HFILL}},
2017     { &hf_sccp_calling_ansi_point_code_indicator,
2018       { "Point Code Indicator", "sccp.calling.pci",
2019         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
2020         "", HFILL}},
2021     { &hf_sccp_calling_ssn,
2022       { "SubSystem Number", "sccp.calling.ssn",
2023         FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
2024         "", HFILL}},
2025     { &hf_sccp_calling_itu_pc,
2026       { "PC", "sccp.calling.pc",
2027         FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
2028         "", HFILL}},
2029     { &hf_sccp_calling_ansi_pc,
2030       { "PC", "sccp.calling.ansi_pc",
2031         FT_STRING, BASE_NONE, NULL, 0x0,
2032         "", HFILL}},
2033     { &hf_sccp_calling_pc_network,
2034       { "PC Network",
2035         "sccp.calling.network",
2036         FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
2037         "", HFILL }},
2038     { &hf_sccp_calling_pc_cluster,
2039       { "PC Cluster",
2040         "sccp.calling.cluster",
2041         FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
2042         "", HFILL }},
2043     { &hf_sccp_calling_pc_member,
2044       { "PC Member",
2045         "sccp.calling.member",
2046         FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
2047         "", HFILL }},
2048     { &hf_sccp_calling_gt_nai,
2049       { "Nature of Address Indicator",
2050         "sccp.calling.nai",
2051         FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
2052         "", HFILL }},
2053     { &hf_sccp_calling_gt_oe,
2054       { "Odd/Even Indicator",
2055         "sccp.calling.oe",
2056         FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
2057         "", HFILL }},
2058     { &hf_sccp_calling_gt_tt,
2059       { "Translation Type",
2060         "sccp.calling.tt",
2061         FT_UINT8, BASE_HEX, NULL, 0x0,
2062         "", HFILL }},
2063     { &hf_sccp_calling_gt_np,
2064       { "Numbering Plan",
2065         "sccp.calling.np",
2066         FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
2067         "", HFILL }},
2068     { &hf_sccp_calling_gt_es,
2069       { "Encoding Scheme",
2070         "sccp.calling.es",
2071         FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
2072         "", HFILL }},
2073     { &hf_sccp_calling_gt_digits,
2074       { "GT Digits",
2075         "sccp.calling.digits",
2076         FT_STRING, BASE_NONE, NULL, 0x0,
2077         "", HFILL }},
2078
2079     { &hf_sccp_dlr,
2080       { "Destination Local Reference", "sccp.dlr",
2081         FT_UINT24, BASE_HEX, NULL, 0x0,
2082         "", HFILL}},
2083     { &hf_sccp_slr,
2084       { "Source Local Reference", "sccp.slr",
2085         FT_UINT24, BASE_HEX, NULL, 0x0,
2086         "", HFILL}},
2087     { &hf_sccp_class,
2088       { "Class", "sccp.class",
2089         FT_UINT8, BASE_HEX, NULL, CLASS_CLASS_MASK,
2090         "", HFILL}},
2091     { &hf_sccp_handling,
2092       { "Message handling", "sccp.handling",
2093         FT_UINT8, BASE_HEX, VALS(sccp_class_handling_values), CLASS_SPARE_HANDLING_MASK,
2094         "", HFILL}},
2095     { &hf_sccp_more,
2096       { "More data", "sccp.more",
2097         FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEGMENTING_REASSEMBLING_MASK,
2098         "", HFILL}},
2099     { &hf_sccp_rsn,
2100       { "Receive Sequence Number", "sccp.rsn",
2101         FT_UINT8, BASE_HEX, NULL, RSN_MASK,
2102         "", HFILL}},
2103     { &hf_sccp_sequencing_segmenting_ssn,
2104       { "Sequencing Segmenting: Send Sequence Number", "sccp.sequencing_segmenting.ssn",
2105         FT_UINT8, BASE_HEX, NULL, SEND_SEQUENCE_NUMBER_MASK,
2106         "", HFILL}},
2107     { &hf_sccp_sequencing_segmenting_rsn,
2108       { "Sequencing Segmenting: Receive Sequence Number", "sccp.sequencing_segmenting.rsn",
2109         FT_UINT8, BASE_HEX, NULL, RECEIVE_SEQUENCE_NUMBER_MASK,
2110         "", HFILL}},
2111     { &hf_sccp_sequencing_segmenting_more,
2112       { "Sequencing Segmenting: More", "sccp.sequencing_segmenting.more",
2113         FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEQUENCING_SEGMENTING_MORE_MASK,
2114         "", HFILL}},
2115     { &hf_sccp_credit,
2116       { "Credit", "sccp.credit",
2117         FT_UINT8, BASE_HEX, NULL, 0x0,
2118         "", HFILL}},
2119     { &hf_sccp_release_cause,
2120       { "Release Cause", "sccp.release_cause",
2121         FT_UINT8, BASE_HEX, VALS(sccp_release_cause_values), 0x0,
2122         "", HFILL}},
2123     { &hf_sccp_return_cause,
2124       { "Return Cause", "sccp.return_cause",
2125         FT_UINT8, BASE_HEX, VALS(sccp_return_cause_values), 0x0,
2126         "", HFILL}},
2127     { &hf_sccp_reset_cause,
2128       { "Reset Cause", "sccp.reset_cause",
2129         FT_UINT8, BASE_HEX, VALS(sccp_reset_cause_values), 0x0,
2130         "", HFILL}},
2131     { &hf_sccp_error_cause,
2132       { "Error Cause", "sccp.error_cause",
2133         FT_UINT8, BASE_HEX, VALS(sccp_error_cause_values), 0x0,
2134         "", HFILL}},
2135     { &hf_sccp_refusal_cause,
2136       { "Refusal Cause", "sccp.refusal_cause",
2137         FT_UINT8, BASE_HEX, VALS(sccp_refusal_cause_values), 0x0,
2138         "", HFILL}},
2139     { &hf_sccp_segmentation_first,
2140       { "Segmentation: First", "sccp.segmentation.first",
2141         FT_UINT8, BASE_HEX, VALS(sccp_segmentation_first_segment_values), SEGMENTATION_FIRST_SEGMENT_MASK,
2142         "", HFILL}},
2143     { &hf_sccp_segmentation_class,
2144       { "Segmentation: Class", "sccp.segmentation.class",
2145         FT_UINT8, BASE_HEX, VALS(sccp_segmentation_class_values), SEGMENTATION_CLASS_MASK,
2146         "", HFILL}},
2147     { &hf_sccp_segmentation_remaining,
2148       { "Segmentation: Remaining", "sccp.segmentation.remaining",
2149         FT_UINT8, BASE_HEX, NULL, SEGMENTATION_REMAINING_MASK,
2150         "", HFILL}},
2151     { &hf_sccp_segmentation_slr,
2152       { "Segmentation: Source Local Reference", "sccp.segmentation.slr",
2153         FT_UINT24, BASE_HEX, NULL, 0x0,
2154         "", HFILL}},
2155     { &hf_sccp_hop_counter,
2156       { "Hop Counter", "sccp.hops",
2157         FT_UINT8, BASE_HEX, NULL, 0x0,
2158         "", HFILL}},
2159     { &hf_sccp_importance,
2160       { "Importance", "sccp.importance",
2161         FT_UINT8, BASE_HEX, NULL, IMPORTANCE_IMPORTANCE_MASK,
2162         "", HFILL}},
2163
2164     /* ISNI is ANSI only */
2165     { &hf_sccp_ansi_isni_mi,
2166       { "ISNI Mark for Identification Indicator", "sccp.isni.mi",
2167         FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_MI_MASK,
2168         "", HFILL}},
2169     { &hf_sccp_ansi_isni_iri,
2170       { "ISNI Routing Indicator", "sccp.isni.iri",
2171         FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_IRI_MASK,
2172         "", HFILL}},
2173     { &hf_sccp_ansi_isni_ti,
2174       { "ISNI Type Indicator", "sccp.isni.ti",
2175         FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_TI_MASK,
2176         "", HFILL}},
2177     { &hf_sccp_ansi_isni_netspec,
2178       { "ISNI Network Specific (Type 1)", "sccp.isni.netspec",
2179         FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_NETSPEC_MASK,
2180         "", HFILL}},
2181     { &hf_sccp_ansi_isni_counter,
2182       { "ISNI Counter", "sccp.isni.counter",
2183         FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_COUNTER_MASK,
2184         "", HFILL}},
2185   };
2186
2187   /* Setup protocol subtree array */
2188   static gint *ett[] = {
2189     &ett_sccp,
2190     &ett_sccp_called,
2191     &ett_sccp_called_ai,
2192     &ett_sccp_called_pc,
2193     &ett_sccp_called_gt,
2194     &ett_sccp_calling,
2195     &ett_sccp_calling_ai,
2196     &ett_sccp_calling_pc,
2197     &ett_sccp_calling_gt,
2198     &ett_sccp_sequencing_segmenting,
2199     &ett_sccp_segmentation,
2200     &ett_sccp_ansi_isni_routing_control,
2201   };
2202
2203   /* Register the protocol name and description */
2204   proto_sccp = proto_register_protocol("Signalling Connection Control Part",
2205                                        "SCCP", "sccp");
2206
2207   /* Required function calls to register the header fields and subtrees used */
2208   proto_register_field_array(proto_sccp, hf, array_length(hf));
2209   proto_register_subtree_array(ett, array_length(ett));
2210
2211   sccp_ssn_dissector_table = register_dissector_table("sccp.ssn", "SCCP SSN", FT_UINT8, BASE_DEC);
2212
2213 }
2214
2215 void
2216 proto_reg_handoff_sccp(void)
2217 {
2218   dissector_handle_t sccp_handle;
2219
2220   sccp_handle = create_dissector_handle(dissect_sccp, proto_sccp);
2221
2222   dissector_add("mtp3.service_indicator", SCCP_SI, sccp_handle);
2223   dissector_add("m3ua.protocol_data_si", SCCP_SI, sccp_handle);
2224
2225   data_handle = find_dissector("data");
2226 }