Final updates for 0.9.14.
[metze/wireshark/wip.git] / packet-sccp.c
1 /* packet-sccp.c
2  * Routines for Signalling Connection Control Part (SCCP) dissection
3  *
4  * It is hopefully compliant to:
5  *   ANSI T1.112.3-1996
6  *   ITU-T Q.713 7/1996
7  *   YDN 038-1997 (Chinese ITU variant)
8  *
9  * Copyright 2002, Jeff Morriss <jeff.morriss[AT]ulticom.com>
10  *
11  * $Id: packet-sccp.c,v 1.11 2003/06/26 06:28:47 guy Exp $
12  *
13  * Ethereal - Network traffic analyzer
14  * By Gerald Combs <gerald@ethereal.com>
15  * Copyright 1998 Gerald Combs
16  *
17  * Copied from packet-m2pa.c
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License
21  * as published by the Free Software Foundation; either version 2
22  * of the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42 #include <glib.h>
43
44 #ifdef NEED_SNPRINTF_H
45 #include "snprintf.h"
46 #endif
47
48 #include <epan/packet.h>
49 #include "packet-mtp3.h"
50
51 #define SCCP_SI 3
52
53 #define MESSAGE_TYPE_OFFSET 0
54 #define MESSAGE_TYPE_LENGTH 1
55 #define POINTER_LENGTH      1
56 #define POINTER_LENGTH_LONG 2
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 form (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_ansi_pc = -1;
576 static int hf_sccp_called_chinese_pc = -1;
577 static int hf_sccp_called_itu_pc = -1;
578 static int hf_sccp_called_gt_nai = -1;
579 static int hf_sccp_called_gt_oe = -1;
580 static int hf_sccp_called_gt_tt = -1;
581 static int hf_sccp_called_gt_np = -1;
582 static int hf_sccp_called_gt_es = -1;
583 static int hf_sccp_called_gt_digits = -1;
584
585 /* Calling party address */
586 static int hf_sccp_calling_national_indicator = -1;
587 static int hf_sccp_calling_routing_indicator = -1;
588 static int hf_sccp_calling_itu_global_title_indicator = -1;
589 static int hf_sccp_calling_ansi_global_title_indicator = -1;
590 static int hf_sccp_calling_itu_ssn_indicator = -1;
591 static int hf_sccp_calling_itu_point_code_indicator = -1;
592 static int hf_sccp_calling_ansi_ssn_indicator = -1;
593 static int hf_sccp_calling_ansi_point_code_indicator = -1;
594 static int hf_sccp_calling_ssn = -1;
595 static int hf_sccp_calling_pc_member = -1;
596 static int hf_sccp_calling_pc_cluster = -1;
597 static int hf_sccp_calling_pc_network = -1;
598 static int hf_sccp_calling_ansi_pc = -1;
599 static int hf_sccp_calling_chinese_pc = -1;
600 static int hf_sccp_calling_itu_pc = -1;
601 static int hf_sccp_calling_gt_nai = -1;
602 static int hf_sccp_calling_gt_oe = -1;
603 static int hf_sccp_calling_gt_tt = -1;
604 static int hf_sccp_calling_gt_np = -1;
605 static int hf_sccp_calling_gt_es = -1;
606 static int hf_sccp_calling_gt_digits = -1;
607
608 /* Other parameter values */
609 static int hf_sccp_dlr = -1;
610 static int hf_sccp_slr = -1;
611 static int hf_sccp_class = -1;
612 static int hf_sccp_handling = -1;
613 static int hf_sccp_more = -1;
614 static int hf_sccp_rsn = -1;
615 static int hf_sccp_sequencing_segmenting_ssn = -1;
616 static int hf_sccp_sequencing_segmenting_rsn = -1;
617 static int hf_sccp_sequencing_segmenting_more = -1;
618 static int hf_sccp_credit = -1;
619 static int hf_sccp_release_cause = -1;
620 static int hf_sccp_return_cause = -1;
621 static int hf_sccp_reset_cause = -1;
622 static int hf_sccp_error_cause = -1;
623 static int hf_sccp_refusal_cause = -1;
624 static int hf_sccp_segmentation_first = -1;
625 static int hf_sccp_segmentation_class = -1;
626 static int hf_sccp_segmentation_remaining = -1;
627 static int hf_sccp_segmentation_slr = -1;
628 static int hf_sccp_hop_counter = -1;
629 static int hf_sccp_importance = -1;
630 static int hf_sccp_ansi_isni_mi = -1;
631 static int hf_sccp_ansi_isni_iri = -1;
632 static int hf_sccp_ansi_isni_ti = -1;
633 static int hf_sccp_ansi_isni_netspec = -1;
634 static int hf_sccp_ansi_isni_counter = -1;
635
636
637 /* Initialize the subtree pointers */
638 static gint ett_sccp = -1;
639 static gint ett_sccp_called = -1;
640 static gint ett_sccp_called_ai = -1;
641 static gint ett_sccp_called_pc = -1;
642 static gint ett_sccp_called_gt = -1;
643 static gint ett_sccp_calling = -1;
644 static gint ett_sccp_calling_ai = -1;
645 static gint ett_sccp_calling_pc = -1;
646 static gint ett_sccp_calling_gt = -1;
647 static gint ett_sccp_sequencing_segmenting = -1;
648 static gint ett_sccp_segmentation = -1;
649 static gint ett_sccp_ansi_isni_routing_control = -1;
650
651
652 /*  Keep track of SSN value of current message so if/when we get to the data
653  *  parameter, we can call appropriate sub-dissector.  TODO: can this info
654  *  be stored elsewhere?
655  */
656 static guint8 called_ssn = INVALID_SSN;
657 static guint8 calling_ssn = INVALID_SSN;
658
659 static dissector_handle_t data_handle;
660 static dissector_table_t sccp_ssn_dissector_table;
661
662 static void
663 dissect_sccp_unknown_message(tvbuff_t *message_tvb, proto_tree *sccp_tree)
664 {
665   guint32 message_length;
666
667   message_length = tvb_length(message_tvb);
668
669   proto_tree_add_text(sccp_tree, message_tvb, 0, message_length,
670                       "Unknown message (%u byte%s)",
671                       message_length, plurality(message_length, "", "s"));
672 }
673
674 static void
675 dissect_sccp_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint16 length)
676 {
677   proto_tree_add_text(tree, tvb, 0, length, "Unknown parameter 0x%x (%u byte%s)",
678                       type, length, plurality(length, "", "s"));
679 }
680
681 static void
682 dissect_sccp_dlr_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
683 {
684   guint32 reference;
685
686   reference = tvb_get_letoh24(tvb, 0);
687   proto_tree_add_uint(tree, hf_sccp_dlr, tvb, 0, length, reference);
688 }
689
690 static void
691 dissect_sccp_slr_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
692 {
693   guint32 reference;
694
695   reference = tvb_get_letoh24(tvb, 0);
696   proto_tree_add_uint(tree, hf_sccp_slr, tvb, 0, length, reference);
697 }
698
699 static void
700 dissect_sccp_gt_address_information(tvbuff_t *tvb, proto_tree *tree,
701                                     guint8 length, gboolean even_length,
702                                     gboolean called)
703 {
704   guint8 offset = 0;
705   guint8 odd_signal, even_signal = 0x0f;
706   char gt_digits[GT_MAX_SIGNALS] = { 0 };
707
708   while(offset < length)
709   {
710     odd_signal = tvb_get_guint8(tvb, offset) & GT_ODD_SIGNAL_MASK;
711     even_signal = tvb_get_guint8(tvb, offset) & GT_EVEN_SIGNAL_MASK;
712     even_signal >>= GT_EVEN_SIGNAL_SHIFT;
713
714     strcat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values,
715                                  "Unknown"));
716
717     /* If the last signal is NOT filler */
718     if (offset != (length - 1) || even_length == TRUE)
719       strcat(gt_digits, val_to_str(even_signal, sccp_address_signal_values,
720                                    "Unknown"));
721
722     offset += GT_SIGNAL_LENGTH;
723   }
724
725   proto_tree_add_string_format(tree, called ? hf_sccp_called_gt_digits
726                                             : hf_sccp_calling_gt_digits,
727                              tvb, 0, length,
728                              gt_digits,
729                              "Address information (digits): %s", gt_digits);
730   proto_tree_add_string_hidden(tree, called ? hf_sccp_gt_digits
731                                             : hf_sccp_gt_digits,
732                              tvb, 0, length,
733                              gt_digits);
734 }
735
736 static void
737 dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint8 length,
738                           guint8 gti, gboolean called)
739 {
740   proto_item *gt_item = 0;
741   proto_tree *gt_tree = 0;
742   tvbuff_t *signals_tvb;
743   guint8 offset = 0;
744   guint8 odd_even, nai, tt, np, es;
745   gboolean even = TRUE;
746
747   /* Shift GTI to where we can work with it */
748   gti >>= GTI_SHIFT;
749
750   gt_item = proto_tree_add_text(tree, tvb, offset, length,
751                                 "Global Title 0x%x (%u byte%s)",
752                                 gti, length, plurality(length,"", "s"));
753   gt_tree = proto_item_add_subtree(gt_item, called ? ett_sccp_called_gt
754                                                    : ett_sccp_calling_gt);
755
756   /* Decode Transation Type (if present) */
757   switch (gti) {
758   case AI_GTI_TT:
759
760     /* Protocol doesn't tell us, so we ASSUME even... */
761     even = TRUE;
762     /* Fall through */
763   case ITU_AI_GTI_TT_NP_ES:
764   case ITU_AI_GTI_TT_NP_ES_NAI:
765   case ANSI_AI_GTI_TT_NP_ES:
766
767     tt = tvb_get_guint8(tvb, offset);
768     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_tt
769                                         : hf_sccp_calling_gt_tt,
770                         tvb, offset, GT_TT_LENGTH, tt);
771     offset += GT_TT_LENGTH;
772   }
773
774   /* Decode Numbering Plan and Encoding Scheme (if present) */
775   switch (gti) {
776   case ITU_AI_GTI_TT_NP_ES:
777   case ITU_AI_GTI_TT_NP_ES_NAI:
778   case ANSI_AI_GTI_TT_NP_ES:
779
780     np = tvb_get_guint8(tvb, offset) & GT_NP_MASK;
781     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_np
782                                         : hf_sccp_calling_gt_np,
783                         tvb, offset, GT_NP_ES_LENGTH, np);
784
785     es = tvb_get_guint8(tvb, offset) & GT_ES_MASK;
786     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_es
787                                         : hf_sccp_calling_gt_es,
788                         tvb, offset, GT_NP_ES_LENGTH, es);
789
790     even = (es == GT_ES_BCD_EVEN) ? TRUE : FALSE;
791
792     offset += GT_NP_ES_LENGTH;
793   }
794
795   /* Decode Odd/Even Indicator (if present) */
796   if (gti == ITU_AI_GTI_NAI) {
797     odd_even = tvb_get_guint8(tvb, offset) & GT_OE_MASK;
798     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_oe
799                                         : hf_sccp_calling_gt_oe,
800                         tvb, offset, GT_NAI_LENGTH, odd_even);
801     even = (odd_even == GT_OE_EVEN) ? TRUE : FALSE;
802
803     /* offset doesn't change */
804   }
805
806   /* Decode Nature of Address Indicator (if present) */
807   switch (gti) {
808   case ITU_AI_GTI_NAI:
809   case ITU_AI_GTI_TT_NP_ES_NAI:
810     nai = tvb_get_guint8(tvb, offset) & GT_NAI_MASK;
811     proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_nai
812                                         : hf_sccp_calling_gt_nai,
813                         tvb, offset, GT_NAI_LENGTH, nai);
814
815     offset += GT_NAI_LENGTH;
816   }
817
818   /* Decode address signal(s) */
819   signals_tvb = tvb_new_subset(tvb, offset, (length - offset),
820                                (length - offset));
821   dissect_sccp_gt_address_information(signals_tvb, gt_tree, (length - offset),
822                                       even,
823                                       called);
824 }
825
826 static int
827 dissect_sccp_3byte_pc(tvbuff_t *tvb, proto_tree *call_tree, guint8 offset,
828                      gboolean called)
829 {
830   guint32 dpc;
831   proto_item *call_pc_item = 0;
832   proto_tree *call_pc_tree = 0;
833   char pc[ANSI_PC_STRING_LENGTH];
834   int *hf_pc;
835
836   if (mtp3_standard == ANSI_STANDARD)
837   {
838     if (called)
839       hf_pc = &hf_sccp_called_ansi_pc;
840     else
841       hf_pc = &hf_sccp_calling_ansi_pc;
842   } else /* CHINESE_ITU_STANDARD */ {
843     if (called)
844       hf_pc = &hf_sccp_called_chinese_pc;
845     else
846       hf_pc = &hf_sccp_calling_chinese_pc;
847   }
848
849   /* create the DPC tree; modified from that in packet-mtp3.c */
850   dpc = tvb_get_ntoh24(tvb, offset);
851   snprintf(pc, sizeof(pc), "%d-%d-%d", (dpc & ANSI_NETWORK_MASK),
852                                        ((dpc & ANSI_CLUSTER_MASK) >> 8),
853                                        ((dpc & ANSI_MEMBER_MASK) >> 16));
854
855   call_pc_item = proto_tree_add_string_format(call_tree, *hf_pc,
856                                               tvb, offset, ANSI_PC_LENGTH,
857                                               pc, "PC (%s)", pc);
858
859   call_pc_tree = proto_item_add_subtree(call_pc_item,
860                                           called ? ett_sccp_called_pc
861                                                  : ett_sccp_calling_pc);
862
863   proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_member
864                                            : hf_sccp_calling_pc_member,
865                       tvb, offset, ANSI_NCM_LENGTH, dpc);
866   offset += ANSI_NCM_LENGTH;
867   proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_cluster
868                                            : hf_sccp_calling_pc_cluster,
869                       tvb, offset, ANSI_NCM_LENGTH, dpc);
870   offset += ANSI_NCM_LENGTH;
871   proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_network
872                                            : hf_sccp_calling_pc_network,
873                       tvb, offset, ANSI_NCM_LENGTH, dpc);
874   offset += ANSI_NCM_LENGTH;
875
876   return(offset);
877 }
878
879 /*  FUNCTION dissect_sccp_called_calling_param():
880  *  Dissect the Calling or Called Party Address parameters.
881  *
882  *  The boolean 'called' describes whether this function is decoding a
883  *  called (TRUE) or calling (FALSE) party address.  There is simply too
884  *  much code in this function to have 2 copies of it (one for called, one
885  *  for calling).
886  *
887  *  NOTE:  this function is called even when (!tree) so that we can get
888  *  the SSN and subsequently call subdissectors (if and when there's a data
889  *  parameter).  Realistically we should put if (!tree)'s around a lot of the
890  *  code, but I think that would make it unreadable--and the expense of not
891  *  doing so does not appear to be very high.
892  */
893 static void
894 dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree,
895                                   guint8 length, gboolean called)
896 {
897   proto_item *call_item = 0, *call_ai_item = 0;
898   proto_tree *call_tree = 0, *call_ai_tree = 0;
899   guint8 offset;
900   guint8 national = -1, routing_ind, gti, pci, ssni, ssn;
901   guint32 dpc;
902   tvbuff_t *gt_tvb;
903
904   call_item = proto_tree_add_text(tree, tvb, 0, length,
905                                     "%s Party address (%u byte%s)",
906                                     called ? "Called" : "Calling", length,
907                                     plurality(length, "", "s"));
908   call_tree = proto_item_add_subtree(call_item, called ? ett_sccp_called
909                                                        : ett_sccp_calling);
910
911   call_ai_item = proto_tree_add_text(call_tree, tvb, 0,
912                                        ADDRESS_INDICATOR_LENGTH,
913                                        "Address Indicator");
914   call_ai_tree = proto_item_add_subtree(call_ai_item, called ? ett_sccp_called_ai
915                                                              : ett_sccp_calling_ai);
916
917   if (mtp3_standard == ANSI_STANDARD)
918   {
919     national = tvb_get_guint8(tvb, 0) & ANSI_NATIONAL_MASK;
920     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_national_indicator
921                                              : hf_sccp_calling_national_indicator,
922                         tvb, 0, ADDRESS_INDICATOR_LENGTH, national);
923   }
924
925   routing_ind = tvb_get_guint8(tvb, 0) & ROUTING_INDICATOR_MASK;
926   proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_routing_indicator
927                                            : hf_sccp_calling_routing_indicator,
928                       tvb, 0, ADDRESS_INDICATOR_LENGTH, routing_ind);
929
930   gti = tvb_get_guint8(tvb, 0) & GTI_MASK;
931
932   if (mtp3_standard == ITU_STANDARD ||
933       mtp3_standard == CHINESE_ITU_STANDARD ||
934       national == 0) {
935
936     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_global_title_indicator
937                                              : hf_sccp_called_itu_global_title_indicator,
938                         tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
939
940     ssni = tvb_get_guint8(tvb, 0) & ITU_SSN_INDICATOR_MASK;
941     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_ssn_indicator
942                                              : hf_sccp_calling_itu_ssn_indicator,
943                         tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
944
945     pci = tvb_get_guint8(tvb, 0) & ITU_PC_INDICATOR_MASK;
946     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_point_code_indicator
947                                              : hf_sccp_calling_itu_point_code_indicator,
948                         tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
949
950     offset = ADDRESS_INDICATOR_LENGTH;
951
952     /* Dissect PC (if present) */
953     if (pci) {
954       if (mtp3_standard == ITU_STANDARD)
955       {
956
957         dpc = tvb_get_letohs(tvb, offset) & ITU_PC_MASK;
958         proto_tree_add_uint(call_tree, called ? hf_sccp_called_itu_pc
959                                               : hf_sccp_calling_itu_pc,
960                             tvb, offset, ITU_PC_LENGTH, dpc);
961         offset += ITU_PC_LENGTH;
962
963       } else /* CHINESE_ITU_STANDARD */ {
964
965         offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
966
967       }
968     }
969
970     /* Dissect SSN (if present) */
971     if (ssni) {
972       ssn = tvb_get_guint8(tvb, offset);
973       if (called) {
974               called_ssn = ssn;
975       }
976       else {
977               calling_ssn = ssn;
978       }
979
980       proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
981                                             : hf_sccp_calling_ssn,
982                           tvb, offset, ADDRESS_SSN_LENGTH, ssn);
983       proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
984                                  ADDRESS_SSN_LENGTH, ssn);
985       offset += ADDRESS_SSN_LENGTH;
986     }
987
988     if (!tree)
989       return;   /* got SSN, that's all we need here... */
990
991     /* Dissect GT (if present) */
992     if (gti != AI_GTI_NO_GT) {
993       gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
994                               (length - offset));
995       dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
996                                 called);
997     }
998
999   } else if (mtp3_standard == ANSI_STANDARD) {
1000
1001     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_global_title_indicator
1002                                              : hf_sccp_calling_ansi_global_title_indicator,
1003                         tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
1004
1005     pci = tvb_get_guint8(tvb, 0) & ANSI_PC_INDICATOR_MASK;
1006     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_point_code_indicator
1007                                              : hf_sccp_calling_ansi_point_code_indicator,
1008                         tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
1009
1010     ssni = tvb_get_guint8(tvb, 0) & ANSI_SSN_INDICATOR_MASK;
1011     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator
1012                                              : hf_sccp_calling_ansi_ssn_indicator,
1013                         tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
1014
1015     offset = ADDRESS_INDICATOR_LENGTH;
1016
1017     /* Dissect SSN (if present) */
1018     if (ssni) {
1019       ssn = tvb_get_guint8(tvb, offset);
1020       if (called) {
1021               called_ssn = ssn;
1022       }
1023       else {
1024               calling_ssn = ssn;
1025       }
1026
1027       proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
1028                                             : hf_sccp_calling_ssn,
1029                           tvb, offset, ADDRESS_SSN_LENGTH, ssn);
1030       proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
1031                                  ADDRESS_SSN_LENGTH, ssn);
1032       offset += ADDRESS_SSN_LENGTH;
1033     }
1034
1035     if (!tree)
1036       return;   /* got SSN, that's all we need here... */
1037
1038     /* Dissect PC (if present) */
1039     if (pci) {
1040       offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
1041     }
1042
1043     /* Dissect GT (if present) */
1044     if (gti != AI_GTI_NO_GT) {
1045       gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
1046                               (length - offset));
1047       dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
1048                                 called);
1049     }
1050
1051   }
1052
1053 }
1054
1055 static void
1056 dissect_sccp_called_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1057 {
1058   dissect_sccp_called_calling_param(tvb, tree, length, TRUE);
1059 }
1060
1061 static void
1062 dissect_sccp_calling_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1063 {
1064   dissect_sccp_called_calling_param(tvb, tree, length, FALSE);
1065 }
1066
1067 static void
1068 dissect_sccp_class_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1069 {
1070   guint8 class, handling;
1071
1072   class = tvb_get_guint8(tvb, 0) & CLASS_CLASS_MASK;
1073   handling = tvb_get_guint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK;
1074
1075   proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, class);
1076
1077   if (class == 0 || class == 1)
1078     proto_tree_add_uint(tree, hf_sccp_handling, tvb, 0, length, handling);
1079 }
1080
1081 static void
1082 dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1083 {
1084   guint8 more;
1085
1086   more = tvb_get_guint8(tvb, 0) & SEGMENTING_REASSEMBLING_MASK;
1087   proto_tree_add_uint(tree, hf_sccp_more, tvb, 0, length, more);
1088 }
1089
1090 static void
1091 dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1092 {
1093   guint8 rsn;
1094
1095   rsn = tvb_get_guint8(tvb, 0) >> 1;
1096   proto_tree_add_uint(tree, hf_sccp_rsn, tvb, 0, length, rsn);
1097 }
1098
1099 static void
1100 dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1101 {
1102   guint8 rsn, ssn, more;
1103   proto_item *param_item;
1104   proto_tree *param_tree;
1105
1106   ssn = tvb_get_guint8(tvb, 0) >> 1;
1107   rsn = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) >> 1;
1108   more = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) & SEQUENCING_SEGMENTING_MORE_MASK;
1109
1110   param_item = proto_tree_add_text(tree, tvb, 0, length,
1111                                    val_to_str(PARAMETER_SEQUENCING_SEGMENTING,
1112                                               sccp_parameter_values, "Unknown"));
1113   param_tree = proto_item_add_subtree(param_item,
1114                                       ett_sccp_sequencing_segmenting);
1115
1116   proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_ssn, tvb, 0,
1117                       SEQUENCING_SEGMENTING_SSN_LENGTH, ssn);
1118   proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_rsn, tvb,
1119                       SEQUENCING_SEGMENTING_SSN_LENGTH,
1120                       SEQUENCING_SEGMENTING_RSN_LENGTH, rsn);
1121   proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_more, tvb,
1122                       SEQUENCING_SEGMENTING_SSN_LENGTH,
1123                       SEQUENCING_SEGMENTING_RSN_LENGTH, more);
1124 }
1125
1126 static void
1127 dissect_sccp_credit_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1128 {
1129   guint8 credit;
1130
1131   credit = tvb_get_guint8(tvb, 0);
1132   proto_tree_add_uint(tree, hf_sccp_credit, tvb, 0, length, credit);
1133 }
1134
1135 static void
1136 dissect_sccp_release_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1137 {
1138   guint8 cause;
1139
1140   cause = tvb_get_guint8(tvb, 0);
1141   proto_tree_add_uint(tree, hf_sccp_release_cause, tvb, 0, length, cause);
1142 }
1143
1144 static void
1145 dissect_sccp_return_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1146 {
1147   guint8 cause;
1148
1149   cause = tvb_get_guint8(tvb, 0);
1150   proto_tree_add_uint(tree, hf_sccp_return_cause, tvb, 0, length, cause);
1151 }
1152
1153 static void
1154 dissect_sccp_reset_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1155 {
1156   guint8 cause;
1157
1158   cause = tvb_get_guint8(tvb, 0);
1159   proto_tree_add_uint(tree, hf_sccp_reset_cause, tvb, 0, length, cause);
1160 }
1161
1162 static void
1163 dissect_sccp_error_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1164 {
1165   guint8 cause;
1166
1167   cause = tvb_get_guint8(tvb, 0);
1168   proto_tree_add_uint(tree, hf_sccp_error_cause, tvb, 0, length, cause);
1169 }
1170
1171 static void
1172 dissect_sccp_refusal_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1173 {
1174   guint8 cause;
1175
1176   cause = tvb_get_guint8(tvb, 0);
1177   proto_tree_add_uint(tree, hf_sccp_refusal_cause, tvb, 0, length, cause);
1178 }
1179
1180 /* This function is used for both data and long data (ITU only) parameters */
1181 static void
1182 dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1183 {
1184
1185   /* Try subdissectors (if we found a valid SSN on the current message) */
1186   if ((called_ssn != INVALID_SSN &&
1187        dissector_try_port(sccp_ssn_dissector_table, called_ssn, tvb, pinfo,
1188                           tree)) ||
1189       (calling_ssn != INVALID_SSN &&
1190        dissector_try_port(sccp_ssn_dissector_table, calling_ssn, tvb, pinfo,
1191                           tree)))
1192     return;
1193
1194     /* No sub-dissection occured, treat it as raw data */
1195     call_dissector(data_handle, tvb, pinfo, tree);
1196 }
1197
1198 static void
1199 dissect_sccp_segmentation_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1200 {
1201   guint8 first, class, remaining;
1202   guint32 slr;
1203   proto_item *param_item;
1204   proto_tree *param_tree;
1205
1206   first = tvb_get_guint8(tvb, 0) & SEGMENTATION_FIRST_SEGMENT_MASK;
1207   class = tvb_get_guint8(tvb, 0) & SEGMENTATION_CLASS_MASK;
1208   remaining = tvb_get_guint8(tvb, 0) & SEGMENTATION_REMAINING_MASK;
1209
1210   slr = tvb_get_letoh24(tvb, 1);
1211
1212   param_item = proto_tree_add_text(tree, tvb, 0, length,
1213                                    val_to_str(PARAMETER_SEGMENTATION,
1214                                               sccp_parameter_values, "Unknown"));
1215   param_tree = proto_item_add_subtree(param_item, ett_sccp_segmentation);
1216
1217   proto_tree_add_uint(param_tree, hf_sccp_segmentation_first, tvb, 0, length,
1218                       first);
1219   proto_tree_add_uint(param_tree, hf_sccp_segmentation_class, tvb, 0, length,
1220                       class);
1221   proto_tree_add_uint(param_tree, hf_sccp_segmentation_remaining, tvb, 0,
1222                       length, remaining);
1223   proto_tree_add_uint(param_tree, hf_sccp_segmentation_slr, tvb, 1, length,
1224                       slr);
1225 }
1226
1227 static void
1228 dissect_sccp_hop_counter_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1229 {
1230   guint8 hops;
1231
1232   hops = tvb_get_guint8(tvb, 0);
1233   proto_tree_add_uint(tree, hf_sccp_hop_counter, tvb, 0, length, hops);
1234 }
1235
1236 static void
1237 dissect_sccp_importance_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1238 {
1239   guint8 importance;
1240
1241   importance = tvb_get_guint8(tvb, 0) & IMPORTANCE_IMPORTANCE_MASK;
1242   proto_tree_add_uint(tree, hf_sccp_importance, tvb, 0, length, importance);
1243 }
1244
1245 static void
1246 dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1247 {
1248   guint8 mi, iri, ti, network, netspec;
1249   guint8 offset = 0;
1250   proto_item *param_item;
1251   proto_tree *param_tree;
1252
1253   /* Create a subtree for ISNI Routing Control */
1254   param_item = proto_tree_add_text(tree, tvb, offset, ANSI_ISNI_ROUTING_CONTROL_LENGTH,
1255                                    "ISNI Routing Control");
1256   param_tree = proto_item_add_subtree(param_item,
1257                                       ett_sccp_ansi_isni_routing_control);
1258
1259   mi = tvb_get_guint8(tvb, offset) & ANSI_ISNI_MI_MASK;
1260   proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_mi, tvb, offset,
1261                       ANSI_ISNI_ROUTING_CONTROL_LENGTH, mi);
1262
1263   iri = tvb_get_guint8(tvb, offset) & ANSI_ISNI_IRI_MASK;
1264   proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_iri, tvb, offset,
1265                       ANSI_ISNI_ROUTING_CONTROL_LENGTH, iri);
1266
1267   ti = tvb_get_guint8(tvb, offset) & ANSI_ISNI_TI_MASK;
1268   proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_ti, tvb, offset,
1269                       ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
1270
1271   offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
1272
1273   if ((ti >> ANSI_ISNI_TI_SHIFT) == ANSI_ISNI_TYPE_1) {
1274     netspec = tvb_get_guint8(tvb, offset) & ANSI_ISNI_NETSPEC_MASK;
1275     proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_netspec, tvb, offset,
1276                         ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
1277     offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
1278   }
1279
1280   while (offset < length) {
1281
1282     network = tvb_get_guint8(tvb, offset);
1283     proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
1284                         "Network ID network: %d", network);
1285     offset++;
1286
1287     network = tvb_get_guint8(tvb, offset);
1288     proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
1289                         "Network ID cluster: %d", network);
1290     offset++;
1291   }
1292
1293 }
1294
1295 /*  FUNCTION dissect_sccp_parameter():
1296  *  Dissect a parameter given its type, offset into tvb, and length.
1297  */
1298 static guint16
1299 dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
1300                        proto_tree *tree, guint8 parameter_type, guint16 offset,
1301                        guint16 parameter_length)
1302 {
1303     tvbuff_t *parameter_tvb;
1304
1305     switch (parameter_type) {
1306     case PARAMETER_CALLED_PARTY_ADDRESS:
1307     case PARAMETER_CALLING_PARTY_ADDRESS:
1308     case PARAMETER_DATA:
1309     case PARAMETER_LONG_DATA:
1310       /*  These parameters must be dissected even if !sccp_tree (so that
1311        *  subdissectors can be called).
1312        */
1313       break;
1314
1315     default:
1316       if (!sccp_tree)
1317         return(parameter_length);
1318
1319     }
1320
1321     parameter_tvb = tvb_new_subset(tvb, offset, parameter_length, parameter_length);
1322
1323     switch (parameter_type) {
1324
1325     case PARAMETER_END_OF_OPTIONAL_PARAMETERS:
1326       proto_tree_add_text(sccp_tree, tvb, offset, parameter_length,
1327                           "End of Optional");
1328       break;
1329
1330     case PARAMETER_DESTINATION_LOCAL_REFERENCE:
1331       dissect_sccp_dlr_param(parameter_tvb, sccp_tree, parameter_length);
1332       break;
1333
1334     case PARAMETER_SOURCE_LOCAL_REFERENCE:
1335       dissect_sccp_slr_param(parameter_tvb, sccp_tree, parameter_length);
1336       break;
1337
1338     case PARAMETER_CALLED_PARTY_ADDRESS:
1339       dissect_sccp_called_param(parameter_tvb, sccp_tree, parameter_length);
1340       break;
1341
1342     case PARAMETER_CALLING_PARTY_ADDRESS:
1343       dissect_sccp_calling_param(parameter_tvb, sccp_tree, parameter_length);
1344       break;
1345
1346     case PARAMETER_CLASS:
1347       dissect_sccp_class_param(parameter_tvb, sccp_tree, parameter_length);
1348       break;
1349
1350     case PARAMETER_SEGMENTING_REASSEMBLING:
1351       dissect_sccp_segmenting_reassembling_param(parameter_tvb, sccp_tree,
1352                                                    parameter_length);
1353       break;
1354
1355     case PARAMETER_RECEIVE_SEQUENCE_NUMBER:
1356       dissect_sccp_receive_sequence_number_param(parameter_tvb, sccp_tree,
1357                                                  parameter_length);
1358       break;
1359
1360     case PARAMETER_SEQUENCING_SEGMENTING:
1361       dissect_sccp_sequencing_segmenting_param(parameter_tvb, sccp_tree,
1362                                                parameter_length);
1363       break;
1364
1365     case PARAMETER_CREDIT:
1366       dissect_sccp_credit_param(parameter_tvb, sccp_tree, parameter_length);
1367       break;
1368
1369     case PARAMETER_RELEASE_CAUSE:
1370       dissect_sccp_release_cause_param(parameter_tvb, sccp_tree, parameter_length);
1371       break;
1372
1373     case PARAMETER_RETURN_CAUSE:
1374       dissect_sccp_return_cause_param(parameter_tvb, sccp_tree, parameter_length);
1375       break;
1376
1377     case PARAMETER_RESET_CAUSE:
1378       dissect_sccp_reset_cause_param(parameter_tvb, sccp_tree, parameter_length);
1379       break;
1380
1381     case PARAMETER_ERROR_CAUSE:
1382       dissect_sccp_error_cause_param(parameter_tvb, sccp_tree, parameter_length);
1383       break;
1384
1385     case PARAMETER_REFUSAL_CAUSE:
1386       dissect_sccp_refusal_cause_param(parameter_tvb, sccp_tree, parameter_length);
1387       break;
1388
1389     case PARAMETER_DATA:
1390       dissect_sccp_data_param(parameter_tvb, pinfo, tree);
1391
1392       /* TODO? Re-adjust length of SCCP item since it may be sub-dissected */
1393       /* sccp_length = proto_item_get_len(sccp_item);
1394        * sccp_length -= parameter_length;
1395        * proto_item_set_len(sccp_item, sccp_length);
1396        */
1397       break;
1398
1399     case PARAMETER_SEGMENTATION:
1400       dissect_sccp_segmentation_param(parameter_tvb, sccp_tree, parameter_length);
1401       break;
1402
1403     case PARAMETER_HOP_COUNTER:
1404       dissect_sccp_hop_counter_param(parameter_tvb, sccp_tree, parameter_length);
1405       break;
1406
1407     case PARAMETER_IMPORTANCE:
1408       if (mtp3_standard != ANSI_STANDARD)
1409         dissect_sccp_importance_param(parameter_tvb, sccp_tree, parameter_length);
1410       else
1411         dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1412                                    parameter_length);
1413       break;
1414
1415     case PARAMETER_LONG_DATA:
1416       if (mtp3_standard != ANSI_STANDARD)
1417         dissect_sccp_data_param(parameter_tvb, pinfo, tree);
1418       else
1419         dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1420                                    parameter_length);
1421       break;
1422
1423     case PARAMETER_ISNI:
1424       if (mtp3_standard != ANSI_STANDARD)
1425         dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1426                                    parameter_length);
1427       else
1428         dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
1429       break;
1430
1431     default:
1432       dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1433                                  parameter_length);
1434       break;
1435     }
1436
1437     return(parameter_length);
1438 }
1439
1440 /*  FUNCTION dissect_sccp_variable_parameter():
1441  *  Dissect a variable parameter given its type and offset into tvb.  Length
1442  *  of the parameter is gotten from tvb[0].
1443  *  Length returned is sum of (length + parameter).
1444  */
1445 static guint16
1446 dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo,
1447                                 proto_tree *sccp_tree, proto_tree *tree,
1448                                 guint8 parameter_type, guint16 offset)
1449 {
1450   guint16 parameter_length;
1451   guint8 length_length;
1452
1453   if (parameter_type != PARAMETER_LONG_DATA)
1454   {
1455     parameter_length = tvb_get_guint8(tvb, offset);
1456     length_length = PARAMETER_LENGTH_LENGTH;
1457   }
1458   else
1459   {
1460     /* Long data parameter has 16 bit length */
1461     parameter_length = tvb_get_letohs(tvb, offset);
1462     length_length = PARAMETER_LONG_DATA_LENGTH_LENGTH;
1463   }
1464
1465 /*  TODO? I find this annoying, but it could possibly useful for debugging.
1466  *  Make it a preference?
1467  * if (sccp_tree)
1468  *   proto_tree_add_text(sccp_tree, tvb, offset, length_length,
1469  *                      "%s length: %d",
1470  *                      val_to_str(parameter_type, sccp_parameter_values,
1471  *                                 "Unknown"),
1472  *                      parameter_length);
1473  */
1474
1475   offset += length_length;
1476
1477   dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
1478                          parameter_length);
1479
1480   return(parameter_length + length_length);
1481 }
1482
1483 /*  FUNCTION dissect_sccp_optional_parameters():
1484  *  Dissect all the optional parameters given the start of the optional
1485  *  parameters into tvb.  Parameter types and lengths are read from tvb.
1486  */
1487 static void
1488 dissect_sccp_optional_parameters(tvbuff_t *tvb, packet_info *pinfo,
1489                                  proto_tree *sccp_tree, proto_tree *tree,
1490                                  guint16 offset)
1491 {
1492   guint8 parameter_type;
1493
1494   while ((parameter_type = tvb_get_guint8(tvb, offset)) !=
1495          PARAMETER_END_OF_OPTIONAL_PARAMETERS) {
1496
1497     offset += PARAMETER_TYPE_LENGTH;
1498     offset += dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1499                                               parameter_type, offset);
1500   }
1501
1502   /* Process end of optional parameters */
1503   dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
1504                          END_OF_OPTIONAL_PARAMETERS_LENGTH);
1505
1506 }
1507
1508
1509 static void
1510 dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
1511                      proto_tree *tree)
1512 {
1513   guint8 message_type;
1514   guint16 variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
1515   guint16 optional_pointer = 0;
1516   guint16 offset = 0;
1517
1518 /* Macro for getting pointer to mandatory variable parameters */
1519 #define VARIABLE_POINTER(var, hf_var, ptr_size) \
1520     if (ptr_size == POINTER_LENGTH) \
1521         var = tvb_get_guint8(tvb, offset); \
1522     else \
1523         var = tvb_get_letohs(tvb, offset); \
1524     proto_tree_add_uint(sccp_tree, hf_var, tvb, \
1525                         offset, ptr_size, var); \
1526     var += offset; \
1527     offset += ptr_size;
1528
1529 /* Macro for getting pointer to optional parameters */
1530 #define OPTIONAL_POINTER(ptr_size) \
1531     if (ptr_size == POINTER_LENGTH) \
1532         optional_pointer = tvb_get_guint8(tvb, offset); \
1533     else \
1534         optional_pointer = tvb_get_letohs(tvb, offset); \
1535     proto_tree_add_uint(sccp_tree, hf_sccp_optional_pointer, tvb, \
1536                         offset, ptr_size, optional_pointer); \
1537     optional_pointer += offset; \
1538     offset += ptr_size;
1539
1540
1541   /* Extract the message type;  all other processing is based on this */
1542   message_type   = tvb_get_guint8(tvb, MESSAGE_TYPE_OFFSET);
1543   offset = MESSAGE_TYPE_LENGTH;
1544
1545   if (check_col(pinfo->cinfo, COL_INFO))
1546     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
1547                     val_to_str(message_type, sccp_message_type_acro_values, "Unknown"));
1548
1549   if (sccp_tree) {
1550     /* add the message type to the protocol tree */
1551     proto_tree_add_uint(sccp_tree, hf_sccp_message_type, tvb,
1552                         MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, message_type);
1553
1554   };
1555
1556   /* Starting a new message dissection; clear the global SSN values */
1557   called_ssn = INVALID_SSN;
1558   calling_ssn = INVALID_SSN;
1559
1560   switch(message_type) {
1561   case MESSAGE_TYPE_CR:
1562     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1563                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1564                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1565     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1566                                      PARAMETER_CLASS, offset,
1567                                      PROTOCOL_CLASS_LENGTH);
1568
1569     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1570     OPTIONAL_POINTER(POINTER_LENGTH)
1571
1572     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1573                                     PARAMETER_CALLED_PARTY_ADDRESS,
1574                                     variable_pointer1);
1575     break;
1576
1577   case MESSAGE_TYPE_CC:
1578     /*  TODO: connection has been established;  theoretically we could keep
1579      *  keep track of the SLR/DLR with the called/calling from the CR and
1580      *  track the connection (e.g., on subsequent messages regarding this
1581      *  SLR we could set the global vars "call*_ssn" so data could get
1582      *  sub-dissected).
1583      */
1584     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1585                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1586                                      offset,
1587                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1588     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1589                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1590                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1591     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1592                                      PARAMETER_CLASS, offset,
1593                                      PROTOCOL_CLASS_LENGTH);
1594     OPTIONAL_POINTER(POINTER_LENGTH)
1595     break;
1596
1597   case MESSAGE_TYPE_CREF:
1598     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1599                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1600                                      offset,
1601                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1602     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1603                                      PARAMETER_REFUSAL_CAUSE, offset,
1604                                      REFUSAL_CAUSE_LENGTH);
1605     OPTIONAL_POINTER(POINTER_LENGTH)
1606     break;
1607
1608   case MESSAGE_TYPE_RLSD:
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_SOURCE_LOCAL_REFERENCE,
1615                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1616     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1617                                      PARAMETER_RELEASE_CAUSE, offset,
1618                                      RELEASE_CAUSE_LENGTH);
1619
1620     OPTIONAL_POINTER(POINTER_LENGTH)
1621     break;
1622
1623   case MESSAGE_TYPE_RLC:
1624     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1625                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1626                                      offset,
1627                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1628     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1629                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1630                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1631     break;
1632
1633   case MESSAGE_TYPE_DT1:
1634     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1635                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1636                                      offset,
1637                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1638     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1639                                      PARAMETER_SEGMENTING_REASSEMBLING,
1640                                      offset, SEGMENTING_REASSEMBLING_LENGTH);
1641
1642     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1643     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1644                                     variable_pointer1);
1645     break;
1646
1647   case MESSAGE_TYPE_DT2:
1648     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1649                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1650                                      offset,
1651                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1652     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1653                                      PARAMETER_SEQUENCING_SEGMENTING, offset,
1654                                      SEQUENCING_SEGMENTING_LENGTH);
1655     break;
1656
1657   case MESSAGE_TYPE_AK:
1658     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1659                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1660                                      offset,
1661                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1662     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1663                                      PARAMETER_RECEIVE_SEQUENCE_NUMBER,
1664                                      offset, RECEIVE_SEQUENCE_NUMBER_LENGTH);
1665     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1666                                      PARAMETER_CREDIT, offset, CREDIT_LENGTH);
1667     break;
1668
1669   case MESSAGE_TYPE_UDT:
1670     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1671                                      PARAMETER_CLASS, offset,
1672                                      PROTOCOL_CLASS_LENGTH);
1673     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1674     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
1675     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
1676
1677     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1678                                     PARAMETER_CALLED_PARTY_ADDRESS,
1679                                     variable_pointer1);
1680     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1681                                     PARAMETER_CALLING_PARTY_ADDRESS,
1682                                     variable_pointer2);
1683     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1684                                     variable_pointer3);
1685     break;
1686
1687   case MESSAGE_TYPE_UDTS:
1688     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1689                                      PARAMETER_RETURN_CAUSE, offset,
1690                                      RETURN_CAUSE_LENGTH);
1691
1692     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1693     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
1694     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
1695
1696     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1697                                     PARAMETER_CALLED_PARTY_ADDRESS,
1698                                     variable_pointer1);
1699
1700     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1701                                     PARAMETER_CALLING_PARTY_ADDRESS,
1702                                     variable_pointer2);
1703
1704     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1705                                     variable_pointer3);
1706     break;
1707
1708   case MESSAGE_TYPE_ED:
1709     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1710                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1711                                      offset,
1712                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1713
1714     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1715     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1716                                     variable_pointer1);
1717     break;
1718
1719   case MESSAGE_TYPE_EA:
1720     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1721                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1722                                      offset,
1723                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1724     break;
1725
1726   case MESSAGE_TYPE_RSR:
1727     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1728                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1729                                      offset,
1730                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1731     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1732                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1733                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1734     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1735                                      PARAMETER_RESET_CAUSE, offset,
1736                                      RESET_CAUSE_LENGTH);
1737     break;
1738
1739   case MESSAGE_TYPE_RSC:
1740     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1741                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1742                                      offset,
1743                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1744     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1745                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1746                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1747     break;
1748
1749   case MESSAGE_TYPE_ERR:
1750     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1751                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1752                                      offset,
1753                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1754     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1755                                      PARAMETER_ERROR_CAUSE, offset,
1756                                      ERROR_CAUSE_LENGTH);
1757     break;
1758
1759   case MESSAGE_TYPE_IT:
1760     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1761                                      PARAMETER_DESTINATION_LOCAL_REFERENCE,
1762                                      offset,
1763                                      DESTINATION_LOCAL_REFERENCE_LENGTH);
1764     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1765                                      PARAMETER_SOURCE_LOCAL_REFERENCE,
1766                                      offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1767     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1768                                      PARAMETER_CLASS, offset,
1769                                      PROTOCOL_CLASS_LENGTH);
1770     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1771                                      PARAMETER_SEQUENCING_SEGMENTING,
1772                                      offset, SEQUENCING_SEGMENTING_LENGTH);
1773     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1774                                      PARAMETER_CREDIT, offset, CREDIT_LENGTH);
1775     break;
1776
1777   case MESSAGE_TYPE_XUDT:
1778     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1779                                      PARAMETER_CLASS, offset,
1780                                      PROTOCOL_CLASS_LENGTH);
1781     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1782                                      PARAMETER_HOP_COUNTER, offset,
1783                                      HOP_COUNTER_LENGTH);
1784
1785     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1786     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
1787     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
1788     OPTIONAL_POINTER(POINTER_LENGTH)
1789
1790     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1791                                     PARAMETER_CALLED_PARTY_ADDRESS,
1792                                     variable_pointer1);
1793     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1794                                     PARAMETER_CALLING_PARTY_ADDRESS,
1795                                     variable_pointer2);
1796     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1797                                     variable_pointer3);
1798     break;
1799
1800   case MESSAGE_TYPE_XUDTS:
1801     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1802                                      PARAMETER_RETURN_CAUSE, offset,
1803                                      RETURN_CAUSE_LENGTH);
1804     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1805                                      PARAMETER_HOP_COUNTER, offset,
1806                                      HOP_COUNTER_LENGTH);
1807
1808     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1809     VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
1810     VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
1811     OPTIONAL_POINTER(POINTER_LENGTH)
1812
1813     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1814                                     PARAMETER_CALLED_PARTY_ADDRESS,
1815                                     variable_pointer1);
1816     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1817                                     PARAMETER_CALLING_PARTY_ADDRESS,
1818                                     variable_pointer2);
1819     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1820                                     variable_pointer3);
1821     break;
1822
1823   case MESSAGE_TYPE_LUDT:
1824     if (mtp3_standard != ANSI_STANDARD)
1825     {
1826       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1827                                        PARAMETER_CLASS, offset,
1828                                        PROTOCOL_CLASS_LENGTH);
1829       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1830                                        PARAMETER_HOP_COUNTER, offset,
1831                                        HOP_COUNTER_LENGTH);
1832
1833       VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
1834       VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
1835       VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
1836       OPTIONAL_POINTER(POINTER_LENGTH_LONG)
1837
1838       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1839                                       PARAMETER_CALLED_PARTY_ADDRESS,
1840                                       variable_pointer1);
1841       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1842                                       PARAMETER_CALLING_PARTY_ADDRESS,
1843                                       variable_pointer2);
1844       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1845                                       PARAMETER_LONG_DATA, variable_pointer3);
1846     } else
1847       dissect_sccp_unknown_message(tvb, sccp_tree);
1848     break;
1849
1850   case MESSAGE_TYPE_LUDTS:
1851     if (mtp3_standard != ANSI_STANDARD)
1852     {
1853       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1854                                        PARAMETER_RETURN_CAUSE, offset,
1855                                        RETURN_CAUSE_LENGTH);
1856       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1857                                        PARAMETER_HOP_COUNTER, offset,
1858                                        HOP_COUNTER_LENGTH);
1859
1860       VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
1861       VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
1862       VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
1863       OPTIONAL_POINTER(POINTER_LENGTH_LONG)
1864
1865       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1866                                       PARAMETER_CALLED_PARTY_ADDRESS,
1867                                       variable_pointer1);
1868       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1869                                       PARAMETER_CALLING_PARTY_ADDRESS,
1870                                       variable_pointer2);
1871       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1872                                       PARAMETER_LONG_DATA, variable_pointer3);
1873     } else
1874       dissect_sccp_unknown_message(tvb, sccp_tree);
1875     break;
1876
1877   default:
1878     dissect_sccp_unknown_message(tvb, sccp_tree);
1879   }
1880
1881   if (optional_pointer)
1882     dissect_sccp_optional_parameters(tvb, pinfo, sccp_tree, tree,
1883                                      optional_pointer);
1884
1885 }
1886
1887 static void
1888 dissect_sccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1889 {
1890   proto_item *sccp_item;
1891   proto_tree *sccp_tree = NULL;
1892
1893   /* Make entry in the Protocol column on summary display */
1894   if (check_col(pinfo->cinfo, COL_PROTOCOL))
1895     col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP");
1896
1897   /* In the interest of speed, if "tree" is NULL, don't do any work not
1898      necessary to generate protocol tree items. */
1899   if (tree) {
1900     /* create the sccp protocol tree */
1901     sccp_item = proto_tree_add_item(tree, proto_sccp, tvb, 0, -1, FALSE);
1902     sccp_tree = proto_item_add_subtree(sccp_item, ett_sccp);
1903   }
1904
1905   /* dissect the message */
1906   dissect_sccp_message(tvb, pinfo, sccp_tree, tree);
1907 }
1908
1909 /* Register the protocol with Ethereal */
1910 void
1911 proto_register_sccp(void)
1912 {
1913   /* Setup list of header fields */
1914   static hf_register_info hf[] = {
1915     { &hf_sccp_message_type,
1916       { "Message Type", "sccp.message_type",
1917         FT_UINT8, BASE_HEX, VALS(sccp_message_type_values), 0x0,
1918         "", HFILL}},
1919     { &hf_sccp_variable_pointer1,
1920       { "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1",
1921         FT_UINT16, BASE_DEC, NULL, 0x0,
1922         "", HFILL}},
1923     { &hf_sccp_variable_pointer2,
1924       { "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2",
1925         FT_UINT16, BASE_DEC, NULL, 0x0,
1926         "", HFILL}},
1927     { &hf_sccp_variable_pointer3,
1928       { "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3",
1929         FT_UINT16, BASE_DEC, NULL, 0x0,
1930         "", HFILL}},
1931     { &hf_sccp_optional_pointer,
1932       { "Pointer to Optional parameter", "sccp.optional_pointer",
1933         FT_UINT16, BASE_DEC, NULL, 0x0,
1934         "", HFILL}},
1935     { &hf_sccp_ssn,
1936       { "Called or Calling SubSystem Number", "sccp.ssn",
1937         FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
1938         "", HFILL}},
1939     { &hf_sccp_gt_digits,
1940       { "Called or Calling GT Digits",
1941         "sccp.digits",
1942         FT_STRING, BASE_NONE, NULL, 0x0,
1943         "", HFILL }},
1944
1945     { &hf_sccp_called_national_indicator,
1946       { "National Indicator", "sccp.called.ni",
1947         FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
1948         "", HFILL}},
1949     { &hf_sccp_called_routing_indicator,
1950       { "Routing Indicator", "sccp.called.ri",
1951         FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
1952         "", HFILL}},
1953     { &hf_sccp_called_itu_global_title_indicator,
1954       { "Global Title Indicator", "sccp.called.gti",
1955         FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
1956         "", HFILL}},
1957     { &hf_sccp_called_ansi_global_title_indicator,
1958       { "Global Title Indicator", "sccp.called.gti",
1959         FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
1960         "", HFILL}},
1961     { &hf_sccp_called_itu_ssn_indicator,
1962       { "SubSystem Number Indicator", "sccp.called.ssni",
1963         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
1964         "", HFILL}},
1965     { &hf_sccp_called_itu_point_code_indicator,
1966       { "Point Code Indicator", "sccp.called.pci",
1967         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
1968         "", HFILL}},
1969     { &hf_sccp_called_ansi_ssn_indicator,
1970       { "SubSystem Number Indicator", "sccp.called.ssni",
1971         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
1972         "", HFILL}},
1973     { &hf_sccp_called_ansi_point_code_indicator,
1974       { "Point Code Indicator", "sccp.called.pci",
1975         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
1976         "", HFILL}},
1977     { &hf_sccp_called_ssn,
1978       { "SubSystem Number", "sccp.called.ssn",
1979         FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
1980         "", HFILL}},
1981     { &hf_sccp_called_itu_pc,
1982       { "PC", "sccp.called.pc",
1983         FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
1984         "", HFILL}},
1985     { &hf_sccp_called_ansi_pc,
1986       { "PC", "sccp.called.ansi_pc",
1987         FT_STRING, BASE_NONE, NULL, 0x0,
1988         "", HFILL}},
1989     { &hf_sccp_called_chinese_pc,
1990       { "PC", "sccp.called.chinese_pc",
1991         FT_STRING, BASE_NONE, NULL, 0x0,
1992         "", HFILL}},
1993     { &hf_sccp_called_pc_network,
1994       { "PC Network",
1995         "sccp.called.network",
1996         FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
1997         "", HFILL }},
1998     { &hf_sccp_called_pc_cluster,
1999       { "PC Cluster",
2000         "sccp.called.cluster",
2001         FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
2002         "", HFILL }},
2003     { &hf_sccp_called_pc_member,
2004       { "PC Member",
2005         "sccp.called.member",
2006         FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
2007         "", HFILL }},
2008     { &hf_sccp_called_gt_nai,
2009       { "Nature of Address Indicator",
2010         "sccp.called.nai",
2011         FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
2012         "", HFILL }},
2013     { &hf_sccp_called_gt_oe,
2014       { "Odd/Even Indicator",
2015         "sccp.called.oe",
2016         FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
2017         "", HFILL }},
2018     { &hf_sccp_called_gt_tt,
2019       { "Translation Type",
2020         "sccp.called.tt",
2021         FT_UINT8, BASE_HEX, NULL, 0x0,
2022         "", HFILL }},
2023     { &hf_sccp_called_gt_np,
2024       { "Numbering Plan",
2025         "sccp.called.np",
2026         FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
2027         "", HFILL }},
2028     { &hf_sccp_called_gt_es,
2029       { "Encoding Scheme",
2030         "sccp.called.es",
2031         FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
2032         "", HFILL }},
2033     { &hf_sccp_called_gt_digits,
2034       { "GT Digits",
2035         "sccp.called.digits",
2036         FT_STRING, BASE_NONE, NULL, 0x0,
2037         "", HFILL }},
2038
2039     { &hf_sccp_calling_national_indicator,
2040       { "National Indicator", "sccp.calling.ni",
2041         FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
2042         "", HFILL}},
2043     { &hf_sccp_calling_routing_indicator,
2044       { "Routing Indicator", "sccp.calling.ri",
2045         FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
2046         "", HFILL}},
2047     { &hf_sccp_calling_itu_global_title_indicator,
2048       { "Global Title Indicator", "sccp.calling.gti",
2049         FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
2050         "", HFILL}},
2051     { &hf_sccp_calling_ansi_global_title_indicator,
2052       { "Global Title Indicator", "sccp.calling.gti",
2053         FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
2054         "", HFILL}},
2055     { &hf_sccp_calling_itu_ssn_indicator,
2056       { "SubSystem Number Indicator", "sccp.calling.ssni",
2057         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
2058         "", HFILL}},
2059     { &hf_sccp_calling_itu_point_code_indicator,
2060       { "Point Code Indicator", "sccp.calling.pci",
2061         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
2062         "", HFILL}},
2063     { &hf_sccp_calling_ansi_ssn_indicator,
2064       { "SubSystem Number Indicator", "sccp.calling.ssni",
2065         FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
2066         "", HFILL}},
2067     { &hf_sccp_calling_ansi_point_code_indicator,
2068       { "Point Code Indicator", "sccp.calling.pci",
2069         FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
2070         "", HFILL}},
2071     { &hf_sccp_calling_ssn,
2072       { "SubSystem Number", "sccp.calling.ssn",
2073         FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
2074         "", HFILL}},
2075     { &hf_sccp_calling_itu_pc,
2076       { "PC", "sccp.calling.pc",
2077         FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
2078         "", HFILL}},
2079     { &hf_sccp_calling_ansi_pc,
2080       { "PC", "sccp.calling.ansi_pc",
2081         FT_STRING, BASE_NONE, NULL, 0x0,
2082         "", HFILL}},
2083     { &hf_sccp_calling_chinese_pc,
2084       { "PC", "sccp.calling.chinese_pc",
2085         FT_STRING, BASE_NONE, NULL, 0x0,
2086         "", HFILL}},
2087     { &hf_sccp_calling_pc_network,
2088       { "PC Network",
2089         "sccp.calling.network",
2090         FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
2091         "", HFILL }},
2092     { &hf_sccp_calling_pc_cluster,
2093       { "PC Cluster",
2094         "sccp.calling.cluster",
2095         FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
2096         "", HFILL }},
2097     { &hf_sccp_calling_pc_member,
2098       { "PC Member",
2099         "sccp.calling.member",
2100         FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
2101         "", HFILL }},
2102     { &hf_sccp_calling_gt_nai,
2103       { "Nature of Address Indicator",
2104         "sccp.calling.nai",
2105         FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
2106         "", HFILL }},
2107     { &hf_sccp_calling_gt_oe,
2108       { "Odd/Even Indicator",
2109         "sccp.calling.oe",
2110         FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
2111         "", HFILL }},
2112     { &hf_sccp_calling_gt_tt,
2113       { "Translation Type",
2114         "sccp.calling.tt",
2115         FT_UINT8, BASE_HEX, NULL, 0x0,
2116         "", HFILL }},
2117     { &hf_sccp_calling_gt_np,
2118       { "Numbering Plan",
2119         "sccp.calling.np",
2120         FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
2121         "", HFILL }},
2122     { &hf_sccp_calling_gt_es,
2123       { "Encoding Scheme",
2124         "sccp.calling.es",
2125         FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
2126         "", HFILL }},
2127     { &hf_sccp_calling_gt_digits,
2128       { "GT Digits",
2129         "sccp.calling.digits",
2130         FT_STRING, BASE_NONE, NULL, 0x0,
2131         "", HFILL }},
2132
2133     { &hf_sccp_dlr,
2134       { "Destination Local Reference", "sccp.dlr",
2135         FT_UINT24, BASE_HEX, NULL, 0x0,
2136         "", HFILL}},
2137     { &hf_sccp_slr,
2138       { "Source Local Reference", "sccp.slr",
2139         FT_UINT24, BASE_HEX, NULL, 0x0,
2140         "", HFILL}},
2141     { &hf_sccp_class,
2142       { "Class", "sccp.class",
2143         FT_UINT8, BASE_HEX, NULL, CLASS_CLASS_MASK,
2144         "", HFILL}},
2145     { &hf_sccp_handling,
2146       { "Message handling", "sccp.handling",
2147         FT_UINT8, BASE_HEX, VALS(sccp_class_handling_values), CLASS_SPARE_HANDLING_MASK,
2148         "", HFILL}},
2149     { &hf_sccp_more,
2150       { "More data", "sccp.more",
2151         FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEGMENTING_REASSEMBLING_MASK,
2152         "", HFILL}},
2153     { &hf_sccp_rsn,
2154       { "Receive Sequence Number", "sccp.rsn",
2155         FT_UINT8, BASE_HEX, NULL, RSN_MASK,
2156         "", HFILL}},
2157     { &hf_sccp_sequencing_segmenting_ssn,
2158       { "Sequencing Segmenting: Send Sequence Number", "sccp.sequencing_segmenting.ssn",
2159         FT_UINT8, BASE_HEX, NULL, SEND_SEQUENCE_NUMBER_MASK,
2160         "", HFILL}},
2161     { &hf_sccp_sequencing_segmenting_rsn,
2162       { "Sequencing Segmenting: Receive Sequence Number", "sccp.sequencing_segmenting.rsn",
2163         FT_UINT8, BASE_HEX, NULL, RECEIVE_SEQUENCE_NUMBER_MASK,
2164         "", HFILL}},
2165     { &hf_sccp_sequencing_segmenting_more,
2166       { "Sequencing Segmenting: More", "sccp.sequencing_segmenting.more",
2167         FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEQUENCING_SEGMENTING_MORE_MASK,
2168         "", HFILL}},
2169     { &hf_sccp_credit,
2170       { "Credit", "sccp.credit",
2171         FT_UINT8, BASE_HEX, NULL, 0x0,
2172         "", HFILL}},
2173     { &hf_sccp_release_cause,
2174       { "Release Cause", "sccp.release_cause",
2175         FT_UINT8, BASE_HEX, VALS(sccp_release_cause_values), 0x0,
2176         "", HFILL}},
2177     { &hf_sccp_return_cause,
2178       { "Return Cause", "sccp.return_cause",
2179         FT_UINT8, BASE_HEX, VALS(sccp_return_cause_values), 0x0,
2180         "", HFILL}},
2181     { &hf_sccp_reset_cause,
2182       { "Reset Cause", "sccp.reset_cause",
2183         FT_UINT8, BASE_HEX, VALS(sccp_reset_cause_values), 0x0,
2184         "", HFILL}},
2185     { &hf_sccp_error_cause,
2186       { "Error Cause", "sccp.error_cause",
2187         FT_UINT8, BASE_HEX, VALS(sccp_error_cause_values), 0x0,
2188         "", HFILL}},
2189     { &hf_sccp_refusal_cause,
2190       { "Refusal Cause", "sccp.refusal_cause",
2191         FT_UINT8, BASE_HEX, VALS(sccp_refusal_cause_values), 0x0,
2192         "", HFILL}},
2193     { &hf_sccp_segmentation_first,
2194       { "Segmentation: First", "sccp.segmentation.first",
2195         FT_UINT8, BASE_HEX, VALS(sccp_segmentation_first_segment_values), SEGMENTATION_FIRST_SEGMENT_MASK,
2196         "", HFILL}},
2197     { &hf_sccp_segmentation_class,
2198       { "Segmentation: Class", "sccp.segmentation.class",
2199         FT_UINT8, BASE_HEX, VALS(sccp_segmentation_class_values), SEGMENTATION_CLASS_MASK,
2200         "", HFILL}},
2201     { &hf_sccp_segmentation_remaining,
2202       { "Segmentation: Remaining", "sccp.segmentation.remaining",
2203         FT_UINT8, BASE_HEX, NULL, SEGMENTATION_REMAINING_MASK,
2204         "", HFILL}},
2205     { &hf_sccp_segmentation_slr,
2206       { "Segmentation: Source Local Reference", "sccp.segmentation.slr",
2207         FT_UINT24, BASE_HEX, NULL, 0x0,
2208         "", HFILL}},
2209     { &hf_sccp_hop_counter,
2210       { "Hop Counter", "sccp.hops",
2211         FT_UINT8, BASE_HEX, NULL, 0x0,
2212         "", HFILL}},
2213     { &hf_sccp_importance,
2214       { "Importance", "sccp.importance",
2215         FT_UINT8, BASE_HEX, NULL, IMPORTANCE_IMPORTANCE_MASK,
2216         "", HFILL}},
2217
2218     /* ISNI is ANSI only */
2219     { &hf_sccp_ansi_isni_mi,
2220       { "ISNI Mark for Identification Indicator", "sccp.isni.mi",
2221         FT_UINT8, BASE_HEX, VALS(sccp_isni_mark_for_id_values), ANSI_ISNI_MI_MASK,
2222         "", HFILL}},
2223     { &hf_sccp_ansi_isni_iri,
2224       { "ISNI Routing Indicator", "sccp.isni.iri",
2225         FT_UINT8, BASE_HEX, VALS(sccp_isni_iri_values), ANSI_ISNI_IRI_MASK,
2226         "", HFILL}},
2227     { &hf_sccp_ansi_isni_ti,
2228       { "ISNI Type Indicator", "sccp.isni.ti",
2229         FT_UINT8, BASE_HEX, VALS(sccp_isni_ti_values), ANSI_ISNI_TI_MASK,
2230         "", HFILL}},
2231     { &hf_sccp_ansi_isni_netspec,
2232       { "ISNI Network Specific (Type 1)", "sccp.isni.netspec",
2233         FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_NETSPEC_MASK,
2234         "", HFILL}},
2235     { &hf_sccp_ansi_isni_counter,
2236       { "ISNI Counter", "sccp.isni.counter",
2237         FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_COUNTER_MASK,
2238         "", HFILL}},
2239   };
2240
2241   /* Setup protocol subtree array */
2242   static gint *ett[] = {
2243     &ett_sccp,
2244     &ett_sccp_called,
2245     &ett_sccp_called_ai,
2246     &ett_sccp_called_pc,
2247     &ett_sccp_called_gt,
2248     &ett_sccp_calling,
2249     &ett_sccp_calling_ai,
2250     &ett_sccp_calling_pc,
2251     &ett_sccp_calling_gt,
2252     &ett_sccp_sequencing_segmenting,
2253     &ett_sccp_segmentation,
2254     &ett_sccp_ansi_isni_routing_control,
2255   };
2256
2257   /* Register the protocol name and description */
2258   proto_sccp = proto_register_protocol("Signalling Connection Control Part",
2259                                        "SCCP", "sccp");
2260
2261   /* Required function calls to register the header fields and subtrees used */
2262   proto_register_field_array(proto_sccp, hf, array_length(hf));
2263   proto_register_subtree_array(ett, array_length(ett));
2264
2265   sccp_ssn_dissector_table = register_dissector_table("sccp.ssn", "SCCP SSN", FT_UINT8, BASE_DEC);
2266
2267 }
2268
2269 void
2270 proto_reg_handoff_sccp(void)
2271 {
2272   dissector_handle_t sccp_handle;
2273
2274   sccp_handle = create_dissector_handle(dissect_sccp, proto_sccp);
2275
2276   dissector_add("mtp3.service_indicator", SCCP_SI, sccp_handle);
2277   dissector_add("m3ua.protocol_data_si", SCCP_SI, sccp_handle);
2278
2279   data_handle = find_dissector("data");
2280 }