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