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