Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-sccp.c
blob78ea7d9e5438942bdaa32a6292baafbc62c6b22c
1 /* packet-sccp.c
2 * Routines for Signalling Connection Control Part (SCCP) dissection
4 * It is hopefully compliant to:
5 * ANSI T1.112.3-2001
6 * ITU-T Q.713 7/1996
7 * YDN 038-1997 (Chinese ITU variant)
8 * JT-Q713 and NTT-Q713 (Japan)
10 * Note that Japan-specific GTT is incomplete; in particular, the specific
11 * TTs that are defined in TTC and NTT are not decoded in detail.
13 * Copyright 2002, Jeff Morriss <jeff.morriss.ws [AT] gmail.com>
15 * Wireshark - Network traffic analyzer
16 * By Gerald Combs <gerald@wireshark.org>
17 * Copyright 1998 Gerald Combs
19 * Copied from packet-m2pa.c
21 * SPDX-License-Identifier: GPL-2.0-or-later
25 #include "config.h"
28 #include <epan/packet.h>
29 #include <epan/prefs.h>
30 #include <epan/reassemble.h>
31 #include <epan/address_types.h>
32 #include <epan/asn1.h>
33 #include <epan/uat.h>
34 #include <epan/expert.h>
35 #include <epan/tap.h>
36 #include <epan/to_str.h>
37 #include <epan/decode_as.h>
38 #include <epan/proto_data.h>
39 #include <wiretap/wtap.h>
40 #include <wsutil/str_util.h>
41 #include "packet-mtp3.h"
42 #include "packet-tcap.h"
43 #include "packet-sccp.h"
44 #include "packet-e164.h"
45 #include "packet-e212.h"
47 /* function prototypes */
48 void proto_register_sccp(void);
49 void proto_reg_handoff_sccp(void);
51 static Standard_Type decode_mtp3_standard;
53 #define SCCP_MSG_TYPE_OFFSET 0
54 #define SCCP_MSG_TYPE_LENGTH 1
55 #define POINTER_LENGTH 1
56 #define POINTER_LENGTH_LONG 2
58 /* Same as below but with names typed out */
59 static const value_string sccp_message_type_values[] = {
60 { SCCP_MSG_TYPE_CR, "Connection Request" },
61 { SCCP_MSG_TYPE_CC, "Connection Confirm" },
62 { SCCP_MSG_TYPE_CREF, "Connection Refused" },
63 { SCCP_MSG_TYPE_RLSD, "Released" },
64 { SCCP_MSG_TYPE_RLC, "Release Complete" },
65 { SCCP_MSG_TYPE_DT1, "Data Form 1" },
66 { SCCP_MSG_TYPE_DT2, "Data Form 2" },
67 { SCCP_MSG_TYPE_AK, "Data Acknowledgement" },
68 { SCCP_MSG_TYPE_UDT, "Unitdata" },
69 { SCCP_MSG_TYPE_UDTS, "Unitdata Service" },
70 { SCCP_MSG_TYPE_ED, "Expedited Data" },
71 { SCCP_MSG_TYPE_EA, "Expedited Data Acknowledgement" },
72 { SCCP_MSG_TYPE_RSR, "Reset Request" },
73 { SCCP_MSG_TYPE_RSC, "Reset Confirmation" },
74 { SCCP_MSG_TYPE_ERR, "Error" },
75 { SCCP_MSG_TYPE_IT, "Inactivity Timer" },
76 { SCCP_MSG_TYPE_XUDT, "Extended Unitdata" },
77 { SCCP_MSG_TYPE_XUDTS, "Extended Unitdata Service" },
78 { SCCP_MSG_TYPE_LUDT, "Long Unitdata" },
79 { SCCP_MSG_TYPE_LUDTS, "Long Unitdata Service" },
80 { 0, NULL } };
82 /* Same as above but in acronym form (for the Info column) */
83 const value_string sccp_message_type_acro_values[] = {
84 { SCCP_MSG_TYPE_CR, "CR" },
85 { SCCP_MSG_TYPE_CC, "CC" },
86 { SCCP_MSG_TYPE_CREF, "CREF" },
87 { SCCP_MSG_TYPE_RLSD, "RLSD" },
88 { SCCP_MSG_TYPE_RLC, "RLC" },
89 { SCCP_MSG_TYPE_DT1, "DT1" },
90 { SCCP_MSG_TYPE_DT2, "DT2" },
91 { SCCP_MSG_TYPE_AK, "AK" },
92 { SCCP_MSG_TYPE_UDT, "UDT" },
93 { SCCP_MSG_TYPE_UDTS, "UDTS" },
94 { SCCP_MSG_TYPE_ED, "ED" },
95 { SCCP_MSG_TYPE_EA, "EA" },
96 { SCCP_MSG_TYPE_RSR, "RSR" },
97 { SCCP_MSG_TYPE_RSC, "RSC" },
98 { SCCP_MSG_TYPE_ERR, "ERR" },
99 { SCCP_MSG_TYPE_IT, "IT" },
100 { SCCP_MSG_TYPE_XUDT, "XUDT" },
101 { SCCP_MSG_TYPE_XUDTS, "XUDTS" },
102 { SCCP_MSG_TYPE_LUDT, "LUDT" },
103 { SCCP_MSG_TYPE_LUDTS, "LUDTS" },
104 { 0, NULL } };
106 #define PARAMETER_LENGTH_LENGTH 1
107 #define PARAMETER_LONG_DATA_LENGTH_LENGTH 2
108 #define PARAMETER_TYPE_LENGTH 1
110 #define PARAMETER_END_OF_OPTIONAL_PARAMETERS 0x00
111 #define PARAMETER_DESTINATION_LOCAL_REFERENCE 0x01
112 #define PARAMETER_SOURCE_LOCAL_REFERENCE 0x02
113 #define PARAMETER_CALLED_PARTY_ADDRESS 0x03
114 #define PARAMETER_CALLING_PARTY_ADDRESS 0x04
115 #define PARAMETER_CLASS 0x05
116 #define PARAMETER_SEGMENTING_REASSEMBLING 0x06
117 #define PARAMETER_RECEIVE_SEQUENCE_NUMBER 0x07
118 #define PARAMETER_SEQUENCING_SEGMENTING 0x08
119 #define PARAMETER_CREDIT 0x09
120 #define PARAMETER_RELEASE_CAUSE 0x0a
121 #define PARAMETER_RETURN_CAUSE 0x0b
122 #define PARAMETER_RESET_CAUSE 0x0c
123 #define PARAMETER_ERROR_CAUSE 0x0d
124 #define PARAMETER_REFUSAL_CAUSE 0x0e
125 #define PARAMETER_DATA 0x0f
126 #define PARAMETER_SEGMENTATION 0x10
127 #define PARAMETER_HOP_COUNTER 0x11
128 /* Importance is ITU only */
129 #define PARAMETER_IMPORTANCE 0x12
130 #define PARAMETER_LONG_DATA 0x13
131 /* ISNI is ANSI only */
132 #define PARAMETER_ISNI 0xfa
134 static const value_string sccp_parameter_values[] = {
135 { PARAMETER_END_OF_OPTIONAL_PARAMETERS, "End of Optional Parameters" },
136 { PARAMETER_DESTINATION_LOCAL_REFERENCE, "Destination Local Reference" },
137 { PARAMETER_SOURCE_LOCAL_REFERENCE, "Source Local Reference" },
138 { PARAMETER_CALLED_PARTY_ADDRESS, "Called Party Address" },
139 { PARAMETER_CALLING_PARTY_ADDRESS, "Calling Party Address" },
140 { PARAMETER_CLASS, "Protocol Class" },
141 { PARAMETER_SEGMENTING_REASSEMBLING, "Segmenting/Reassembling" },
142 { PARAMETER_RECEIVE_SEQUENCE_NUMBER, "Receive Sequence Number" },
143 { PARAMETER_SEQUENCING_SEGMENTING, "Sequencing/Segmenting" },
144 { PARAMETER_CREDIT, "Credit" },
145 { PARAMETER_RELEASE_CAUSE, "Release Cause" },
146 { PARAMETER_RETURN_CAUSE, "Return Cause" },
147 { PARAMETER_RESET_CAUSE, "Reset Cause" },
148 { PARAMETER_ERROR_CAUSE, "Error Cause" },
149 { PARAMETER_REFUSAL_CAUSE, "Refusal Cause" },
150 { PARAMETER_DATA, "Data" },
151 { PARAMETER_SEGMENTATION, "Segmentation" },
152 { PARAMETER_HOP_COUNTER, "Hop Counter" },
153 { PARAMETER_IMPORTANCE, "Importance (ITU)" },
154 { PARAMETER_LONG_DATA, "Long Data" },
155 { PARAMETER_ISNI, "Intermediate Signaling Network Identification (ANSI)" },
156 { 0, NULL } };
159 #define END_OF_OPTIONAL_PARAMETERS_LENGTH 1
160 #define DESTINATION_LOCAL_REFERENCE_LENGTH 3
161 #define SOURCE_LOCAL_REFERENCE_LENGTH 3
162 #define PROTOCOL_CLASS_LENGTH 1
163 #define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
164 #define CREDIT_LENGTH 1
165 #define RELEASE_CAUSE_LENGTH 1
166 #define RETURN_CAUSE_LENGTH 1
167 #define RESET_CAUSE_LENGTH 1
168 #define ERROR_CAUSE_LENGTH 1
169 #define REFUSAL_CAUSE_LENGTH 1
170 #define HOP_COUNTER_LENGTH 1
171 #define IMPORTANCE_LENGTH 1
174 /* Parts of the Called and Calling Address parameters */
175 /* Address Indicator */
176 #define ADDRESS_INDICATOR_LENGTH 1
177 #define ITU_RESERVED_MASK 0x80
178 #define ANSI_NATIONAL_MASK 0x80
179 #define ROUTING_INDICATOR_MASK 0x40
180 #define GTI_MASK 0x3C
181 #define GTI_SHIFT 2
182 #define ITU_SSN_INDICATOR_MASK 0x02
183 #define ITU_PC_INDICATOR_MASK 0x01
184 #define ANSI_PC_INDICATOR_MASK 0x02
185 #define ANSI_SSN_INDICATOR_MASK 0x01
187 static const value_string sccp_ansi_national_indicator_values[] = {
188 { 0x0, "Address coded to International standard" },
189 { 0x1, "Address coded to National standard" },
190 { 0, NULL } };
192 #define ROUTE_ON_GT 0x0
193 #define ROUTE_ON_SSN 0x1
194 #define ROUTING_INDICATOR_SHIFT 6
195 static const value_string sccp_routing_indicator_values[] = {
196 { ROUTE_ON_GT, "Route on GT" },
197 { ROUTE_ON_SSN, "Route on SSN" },
198 { 0, NULL } };
200 #define AI_GTI_NO_GT 0x0
201 #define ITU_AI_GTI_NAI 0x1
202 #define AI_GTI_TT 0x2
203 #define ITU_AI_GTI_TT_NP_ES 0x3
204 #define ITU_AI_GTI_TT_NP_ES_NAI 0x4
205 static const value_string sccp_itu_global_title_indicator_values[] = {
206 { AI_GTI_NO_GT, "No Global Title" },
207 { ITU_AI_GTI_NAI, "Nature of Address Indicator only" },
208 { AI_GTI_TT, "Translation Type only" },
209 { ITU_AI_GTI_TT_NP_ES, "Translation Type, Numbering Plan, and Encoding Scheme included" },
210 { ITU_AI_GTI_TT_NP_ES_NAI, "Translation Type, Numbering Plan, Encoding Scheme, and Nature of Address Indicator included" },
211 { 0, NULL } };
213 /* #define AI_GTI_NO_GT 0x0 */
214 #define ANSI_AI_GTI_TT_NP_ES 0x1
215 /* #define AI_GTI_TT 0x2 */
216 static const value_string sccp_ansi_global_title_indicator_values[] = {
217 { AI_GTI_NO_GT, "No Global Title" },
218 { ANSI_AI_GTI_TT_NP_ES, "Translation Type, Numbering Plan, and Encoding Scheme included" },
219 { AI_GTI_TT, "Translation Type only" },
220 { 0, NULL } };
222 static const value_string sccp_ai_pci_values[] = {
223 { 0x1, "Point Code present" },
224 { 0x0, "Point Code not present" },
225 { 0, NULL } };
227 static const value_string sccp_ai_ssni_values[] = {
228 { 0x1, "SSN present" },
229 { 0x0, "SSN not present" },
230 { 0, NULL } };
232 #define ADDRESS_SSN_LENGTH 1
233 #define INVALID_SSN 0xff
234 /* Some values from 3GPP TS 23.003 */
235 /* Japan TTC and NTT define a lot of SSNs, some of which conflict with
236 * these. They are not added for now.
238 static const value_string sccp_ssn_values[] = {
239 { 0x00, "SSN not known/not used" },
240 { 0x01, "SCCP management" },
241 { 0x02, "Reserved for ITU-T allocation" },
242 { 0x03, "ISDN User Part" },
243 { 0x04, "OMAP (Operation, Maintenance, and Administration Part)" },
244 { 0x05, "MAP (Mobile Application Part)" },
245 { 0x06, "HLR (Home Location Register)" },
246 { 0x07, "VLR (Visitor Location Register)" },
247 { 0x08, "MSC (Mobile Switching Center)" },
248 { 0x09, "EIC/EIR (Equipment Identifier Center/Equipment Identification Register)" },
249 { 0x0a, "AUC/AC (Authentication Center)" },
250 { 0x0b, "ISDN supplementary services (ITU only)" },
251 { 0x0c, "Reserved for international use (ITU only)" },
252 { 0x0d, "Broadband ISDN edge-to-edge applications (ITU only)" },
253 { 0x0e, "TC test responder (ITU only)" },
254 /* The following national network subsystem numbers have been allocated for use within and
255 * between GSM/UMTS networks:
257 { 0x8e, "RANAP" },
258 { 0x8f, "RNSAP" },
259 { 0x91, "GMLC(MAP)" },
260 { 0x92, "CAP" },
261 { 0x93, "gsmSCF (MAP) or IM-SSF (MAP) or Presence Network Agent" },
262 { 0x94, "SIWF (MAP)" },
263 { 0x95, "SGSN (MAP)" },
264 { 0x96, "GGSN (MAP)" },
265 /* The following national network subsystem numbers have been allocated for use within GSM/UMTS networks:*/
266 { 0xf8, "CSS (MAP)" },
267 { 0xf9, "PCAP" },
268 { 0xfa, "BSC (BSSAP-LE)" },
269 { 0xfb, "MSC (BSSAP-LE)" },
270 { 0xfc, "IOS or SMLC (BSSAP-LE)" },
271 { 0xfd, "BSS O&M (A interface)" },
272 { 0xfe, "BSSAP/BSAP" },
273 { 0, NULL } };
276 /* * * * * * * * * * * * * * * * *
277 * Global Title: ITU GTI == 0001 *
278 * * * * * * * * * * * * * * * * */
279 #define GT_NAI_MASK 0x7F
280 #define GT_NAI_LENGTH 1
281 #define GT_NAI_UNKNOWN 0x00
282 #define GT_NAI_SUBSCRIBER_NUMBER 0x01
283 #define GT_NAI_RESERVED_NATIONAL 0x02
284 #define GT_NAI_NATIONAL_SIG_NUM 0x03
285 #define GT_NAI_INTERNATIONAL_NUM 0x04
286 static const value_string sccp_nai_values[] = {
287 { GT_NAI_UNKNOWN, "NAI unknown" },
288 { GT_NAI_SUBSCRIBER_NUMBER, "Subscriber Number" },
289 { GT_NAI_RESERVED_NATIONAL, "Reserved for national use" },
290 { GT_NAI_NATIONAL_SIG_NUM, "National significant number" },
291 { GT_NAI_INTERNATIONAL_NUM, "International number" },
292 { 0, NULL } };
295 #define GT_OE_MASK 0x80
296 #define GT_OE_EVEN 0
297 #define GT_OE_ODD 1
298 static const value_string sccp_oe_values[] = {
299 { GT_OE_EVEN, "Even number of address signals" },
300 { GT_OE_ODD, "Odd number of address signals" },
301 { 0, NULL } };
303 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 } };
323 /* * * * * * * * * * * * * * * * * * * * *
324 * Global Title: ITU and ANSI GTI == 0010 *
325 * * * * * * * * * * * * * * * * * * * * */
326 #define GT_TT_LENGTH 1
329 /* * * * * * * * * * * * * * * * * * * * * * * * * *
330 * Global Title: ITU GTI == 0011, ANSI GTI == 0001 *
331 * * * * * * * * * * * * * * * * * * * * * * * * * */
332 #define GT_NP_MASK 0xf0
333 #define GT_NP_SHIFT 4
334 #define GT_NP_ES_LENGTH 1
335 #define GT_NP_UNKNOWN 0x00
336 #define GT_NP_ISDN 0x01
337 #define GT_NP_GENERIC_RESERVED 0x02
338 #define GT_NP_DATA 0x03
339 #define GT_NP_TELEX 0x04
340 #define GT_NP_MARITIME_MOBILE 0x05
341 #define GT_NP_LAND_MOBILE 0x06
342 #define GT_NP_ISDN_MOBILE 0x07
343 #define GT_NP_PRIVATE_NETWORK 0x0e
344 #define GT_NP_RESERVED 0x0f
345 static const value_string sccp_np_values[] = {
346 { GT_NP_UNKNOWN, "Unknown" },
347 { GT_NP_ISDN, "ISDN/telephony" },
348 { GT_NP_GENERIC_RESERVED, "Generic (ITU)/Reserved (ANSI)" },
349 { GT_NP_DATA, "Data" },
350 { GT_NP_TELEX, "Telex" },
351 { GT_NP_MARITIME_MOBILE, "Maritime mobile" },
352 { GT_NP_LAND_MOBILE, "Land mobile" },
353 { GT_NP_ISDN_MOBILE, "ISDN/mobile" },
354 { GT_NP_PRIVATE_NETWORK, "Private network or network-specific" },
355 { GT_NP_RESERVED, "Reserved" },
356 { 0, NULL } };
358 #define GT_ES_MASK 0x0f
359 #define GT_ES_UNKNOWN 0x0
360 #define GT_ES_BCD_ODD 0x1
361 #define GT_ES_BCD_EVEN 0x2
362 #define GT_ES_NATIONAL 0x3
363 #define GT_ES_RESERVED 0xf
364 static const value_string sccp_es_values[] = {
365 { GT_ES_UNKNOWN, "Unknown" },
366 { GT_ES_BCD_ODD, "BCD, odd number of digits" },
367 { GT_ES_BCD_EVEN, "BCD, even number of digits" },
368 { GT_ES_NATIONAL, "National specific" },
369 { GT_ES_RESERVED, "Reserved (ITU)/Spare (ANSI)" },
370 { 0, NULL } };
372 /* Address signals above */
375 /* * * * * * * * * * * * * * * * *
376 * Global Title: ITU GTI == 0100 *
377 * * * * * * * * * * * * * * * * */
378 /* NP above */
379 /* ES above */
380 /* NAI above */
381 /* Address signals above */
384 #define CLASS_CLASS_MASK 0xf
385 #define CLASS_SPARE_HANDLING_MASK 0xf0
386 #define CLASS_SPARE_HANDLING_SHIFT 4
387 static const value_string sccp_class_handling_values [] = {
388 { 0x0, "No special options" },
389 { 0x8, "Return message on error" },
390 { 0, NULL } };
393 #define SEGMENTING_REASSEMBLING_LENGTH 1
394 #define SEGMENTING_REASSEMBLING_MASK 0x01
395 #define NO_MORE_DATA 0
396 #define MORE_DATA 1
397 /* This is also used by sequencing-segmenting parameter */
398 static const value_string sccp_segmenting_reassembling_values [] = {
399 { NO_MORE_DATA, "No more data" },
400 { MORE_DATA, "More data" },
401 { 0, NULL } };
404 #define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
405 #define RSN_MASK 0xfe
407 #define SEQUENCING_SEGMENTING_LENGTH 2
408 #define SEQUENCING_SEGMENTING_SSN_LENGTH 1
409 #define SEQUENCING_SEGMENTING_RSN_LENGTH 1
410 #define SEND_SEQUENCE_NUMBER_MASK 0xfe
411 #define RECEIVE_SEQUENCE_NUMBER_MASK 0xfe
412 #define SEQUENCING_SEGMENTING_MORE_MASK 0x01
415 #define CREDIT_LENGTH 1
417 #define RELEASE_CAUSE_LENGTH 1
418 const value_string sccp_release_cause_values [] = {
419 { 0x00, "End user originated" },
420 { 0x01, "End user congestion" },
421 { 0x02, "End user failure" },
422 { 0x03, "SCCP user originated" },
423 { 0x04, "Remote procedure error" },
424 { 0x05, "Inconsistent connection data" },
425 { 0x06, "Access failure" },
426 { 0x07, "Access congestion" },
427 { 0x08, "Subsystem failure" },
428 { 0x09, "Subsystem congestion" },
429 { 0x0a, "MTP failure" },
430 { 0x0b, "Network congestion" },
431 { 0x0c, "Expiration of reset timer" },
432 { 0x0d, "Expiration of receive inactivity timer" },
433 { 0x0e, "Reserved" },
434 { 0x0f, "Unqualified" },
435 { 0x10, "SCCP failure (ITU only)" },
436 { 0, NULL } };
439 #define RETURN_CAUSE_LENGTH 1
440 const value_string sccp_return_cause_values [] = {
441 { 0x00, "No translation for an address of such nature" },
442 { 0x01, "No translation for this specific address" },
443 { 0x02, "Subsystem congestion" },
444 { 0x03, "Subsystem failure" },
445 { 0x04, "Unequipped failure" },
446 { 0x05, "MTP failure" },
447 { 0x06, "Network congestion" },
448 { 0x07, "Unqualified" },
449 { 0x08, "Error in message transport" },
450 { 0x09, "Error in local processing" },
451 { 0x0a, "Destination cannot perform reassembly" },
452 { 0x0b, "SCCP failure" },
453 { 0x0c, "Hop counter violation" },
454 { 0x0d, "Segmentation not supported" },
455 { 0x0e, "Segmentation failure" },
456 { 0xf7, "Message change failure (ANSI only)" },
457 { 0xf8, "Invalid INS routing request (ANSI only)" },
458 { 0xf9, "Invalid ISNI routing request (ANSI only)"},
459 { 0xfa, "Unauthorized message (ANSI only)" },
460 { 0xfb, "Message incompatibility (ANSI only)" },
461 { 0xfc, "Cannot perform ISNI constrained routing (ANSI only)" },
462 { 0xfd, "Redundant ISNI constrained routing (ANSI only)" },
463 { 0xfe, "Unable to perform ISNI identification (ANSI only)" },
464 { 0, NULL } };
467 #define RESET_CAUSE_LENGTH 1
468 const value_string sccp_reset_cause_values [] = {
469 { 0x00, "End user originated" },
470 { 0x01, "SCCP user originated" },
471 { 0x02, "Message out of order - incorrect send sequence number" },
472 { 0x03, "Message out of order - incorrect receive sequence number" },
473 { 0x04, "Remote procedure error - message out of window" },
474 { 0x05, "Remote procedure error - incorrect send sequence number after (re)initialization" },
475 { 0x06, "Remote procedure error - general" },
476 { 0x07, "Remote end user operational" },
477 { 0x08, "Network operational" },
478 { 0x09, "Access operational" },
479 { 0x0a, "Network congestion" },
480 { 0x0b, "Reserved (ITU)/Not obtainable (ANSI)" },
481 { 0x0c, "Unqualified" },
482 { 0, NULL } };
485 #define ERROR_CAUSE_LENGTH 1
486 const value_string sccp_error_cause_values [] = {
487 { 0x00, "Local Reference Number (LRN) mismatch - unassigned destination LRN" },
488 { 0x01, "Local Reference Number (LRN) mismatch - inconsistent source LRN" },
489 { 0x02, "Point code mismatch" },
490 { 0x03, "Service class mismatch" },
491 { 0x04, "Unqualified" },
492 { 0, NULL } };
495 #define REFUSAL_CAUSE_LENGTH 1
496 const value_string sccp_refusal_cause_values [] = {
497 { 0x00, "End user originated" },
498 { 0x01, "End user congestion" },
499 { 0x02, "End user failure" },
500 { 0x03, "SCCP user originated" },
501 { 0x04, "Destination address unknown" },
502 { 0x05, "Destination inaccessible" },
503 { 0x06, "Network resource - QOS not available/non-transient" },
504 { 0x07, "Network resource - QOS not available/transient" },
505 { 0x08, "Access failure" },
506 { 0x09, "Access congestion" },
507 { 0x0a, "Subsystem failure" },
508 { 0x0b, "Subsystem congestion" },
509 { 0x0c, "Expiration of connection establishment timer" },
510 { 0x0d, "Incompatible user data" },
511 { 0x0e, "Reserved" },
512 { 0x0f, "Unqualified" },
513 { 0x10, "Hop counter violation" },
514 { 0x11, "SCCP failure (ITU only)" },
515 { 0x12, "No translation for an address of such nature" },
516 { 0x13, "Unequipped user" },
517 { 0, NULL } };
520 #define SEGMENTATION_LENGTH 4
521 #define SEGMENTATION_FIRST_SEGMENT_MASK 0x80
522 #define SEGMENTATION_CLASS_MASK 0x40
523 #define SEGMENTATION_SPARE_MASK 0x30
524 #define SEGMENTATION_REMAINING_MASK 0x0f
525 static const value_string sccp_segmentation_first_segment_values [] = {
526 { 1, "First segment" },
527 { 0, "Not first segment" },
528 { 0, NULL } };
529 static const value_string sccp_segmentation_class_values [] = {
530 { 0, "Class 0 selected" },
531 { 1, "Class 1 selected" },
532 { 0, NULL } };
535 #define HOP_COUNTER_LENGTH 1
537 #define IMPORTANCE_LENGTH 1
538 #define IMPORTANCE_IMPORTANCE_MASK 0x7
541 #define ANSI_ISNI_ROUTING_CONTROL_LENGTH 1
542 #define ANSI_ISNI_MI_MASK 0x01
543 #define ANSI_ISNI_IRI_MASK 0x06
544 #define ANSI_ISNI_RES_MASK 0x08
545 #define ANSI_ISNI_TI_MASK 0x10
546 #define ANSI_ISNI_TI_SHIFT 4
547 #define ANSI_ISNI_COUNTER_MASK 0xe0
548 #define ANSI_ISNI_NETSPEC_MASK 0x03
550 static const value_string sccp_isni_mark_for_id_values [] = {
551 { 0x0, "Do not identify networks" },
552 { 0x1, "Identify networks" },
553 { 0, NULL } };
555 static const value_string sccp_isni_iri_values [] = {
556 { 0x0, "Neither constrained nor suggested ISNI routing" },
557 { 0x1, "Constrained ISNI routing" },
558 { 0x2, "Reserved for suggested ISNI routing" },
559 { 0x3, "Spare" },
560 { 0, NULL } };
562 #define ANSI_ISNI_TYPE_0 0x0
563 #define ANSI_ISNI_TYPE_1 0x1
564 static const value_string sccp_isni_ti_values [] = {
565 { ANSI_ISNI_TYPE_0, "Type zero ISNI parameter format" },
566 { ANSI_ISNI_TYPE_1, "Type one ISNI parameter format" },
567 { 0, NULL } };
569 /* Laded from e212 hf*/
570 static int hf_assoc_imsi;
572 /* Initialize the protocol and registered fields */
573 static int proto_sccp;
574 static int hf_sccp_message_type;
575 static int hf_sccp_variable_pointer1;
576 static int hf_sccp_variable_pointer2;
577 static int hf_sccp_variable_pointer3;
578 static int hf_sccp_optional_pointer;
579 static int hf_sccp_param_length;
580 static int hf_sccp_ssn;
581 static int hf_sccp_gt_digits;
583 /* Called Party address */
584 static int hf_sccp_called_ansi_national_indicator;
585 static int hf_sccp_called_itu_natl_use_bit;
586 static int hf_sccp_called_routing_indicator;
587 static int hf_sccp_called_itu_global_title_indicator;
588 static int hf_sccp_called_ansi_global_title_indicator;
589 static int hf_sccp_called_itu_ssn_indicator;
590 static int hf_sccp_called_itu_point_code_indicator;
591 static int hf_sccp_called_ansi_ssn_indicator;
592 static int hf_sccp_called_ansi_point_code_indicator;
593 static int hf_sccp_called_ssn;
594 static int hf_sccp_called_pc_member;
595 static int hf_sccp_called_pc_cluster;
596 static int hf_sccp_called_pc_network;
597 static int hf_sccp_called_ansi_pc;
598 static int hf_sccp_called_chinese_pc;
599 static int hf_sccp_called_itu_pc;
600 static int hf_sccp_called_japan_pc;
601 static int hf_sccp_called_gt_nai;
602 static int hf_sccp_called_gt_oe;
603 static int hf_sccp_called_gt_tt;
604 static int hf_sccp_called_gt_np;
605 static int hf_sccp_called_gt_es;
606 static int hf_sccp_called_gt_digits;
607 static int hf_sccp_called_gt_digits_length;
609 /* Calling party address */
610 static int hf_sccp_calling_ansi_national_indicator;
611 static int hf_sccp_calling_itu_natl_use_bit;
612 static int hf_sccp_calling_routing_indicator;
613 static int hf_sccp_calling_itu_global_title_indicator;
614 static int hf_sccp_calling_ansi_global_title_indicator;
615 static int hf_sccp_calling_itu_ssn_indicator;
616 static int hf_sccp_calling_itu_point_code_indicator;
617 static int hf_sccp_calling_ansi_ssn_indicator;
618 static int hf_sccp_calling_ansi_point_code_indicator;
619 static int hf_sccp_calling_ssn;
620 static int hf_sccp_calling_pc_member;
621 static int hf_sccp_calling_pc_cluster;
622 static int hf_sccp_calling_pc_network;
623 static int hf_sccp_calling_ansi_pc;
624 static int hf_sccp_calling_chinese_pc;
625 static int hf_sccp_calling_itu_pc;
626 static int hf_sccp_calling_japan_pc;
627 static int hf_sccp_calling_gt_nai;
628 static int hf_sccp_calling_gt_oe;
629 static int hf_sccp_calling_gt_tt;
630 static int hf_sccp_calling_gt_np;
631 static int hf_sccp_calling_gt_es;
632 static int hf_sccp_calling_gt_digits;
633 static int hf_sccp_calling_gt_digits_length;
635 /* Other parameter values */
636 static int hf_sccp_dlr;
637 static int hf_sccp_slr;
638 static int hf_sccp_lr;
639 static int hf_sccp_class;
640 static int hf_sccp_handling;
641 static int hf_sccp_more;
642 static int hf_sccp_rsn;
643 static int hf_sccp_sequencing_segmenting_ssn;
644 static int hf_sccp_sequencing_segmenting_rsn;
645 static int hf_sccp_sequencing_segmenting_more;
646 static int hf_sccp_credit;
647 static int hf_sccp_release_cause;
648 static int hf_sccp_return_cause;
649 static int hf_sccp_reset_cause;
650 static int hf_sccp_error_cause;
651 static int hf_sccp_refusal_cause;
652 static int hf_sccp_segmentation_first;
653 static int hf_sccp_segmentation_class;
654 static int hf_sccp_segmentation_remaining;
655 static int hf_sccp_segmentation_slr;
656 static int hf_sccp_hop_counter;
657 static int hf_sccp_importance;
658 static int hf_sccp_ansi_isni_mi;
659 static int hf_sccp_ansi_isni_iri;
660 static int hf_sccp_ansi_isni_ti;
661 static int hf_sccp_ansi_isni_netspec;
662 static int hf_sccp_ansi_isni_counter;
663 static int hf_sccp_ansi_isni_network;
664 static int hf_sccp_ansi_isni_cluster;
665 static int hf_sccp_xudt_msg_fragments;
666 static int hf_sccp_xudt_msg_fragment;
667 static int hf_sccp_xudt_msg_fragment_overlap;
668 static int hf_sccp_xudt_msg_fragment_overlap_conflicts;
669 static int hf_sccp_xudt_msg_fragment_multiple_tails;
670 static int hf_sccp_xudt_msg_fragment_too_long_fragment;
671 static int hf_sccp_xudt_msg_fragment_error;
672 static int hf_sccp_xudt_msg_fragment_count;
673 static int hf_sccp_xudt_msg_reassembled_in;
674 static int hf_sccp_xudt_msg_reassembled_length;
675 static int hf_sccp_assoc_msg;
676 static int hf_sccp_assoc_id;
677 static int hf_sccp_segmented_data;
678 static int hf_sccp_linked_dissector;
679 static int hf_sccp_end_optional_param;
680 static int hf_sccp_unknown_message;
681 static int hf_sccp_unknown_parameter;
683 /* Initialize the subtree pointers */
684 static int ett_sccp;
685 static int ett_sccp_called;
686 static int ett_sccp_called_ai;
687 static int ett_sccp_called_pc;
688 static int ett_sccp_called_gt;
689 static int ett_sccp_called_gt_digits;
690 static int ett_sccp_calling;
691 static int ett_sccp_calling_ai;
692 static int ett_sccp_calling_pc;
693 static int ett_sccp_calling_gt;
694 static int ett_sccp_calling_gt_digits;
695 static int ett_sccp_sequencing_segmenting;
696 static int ett_sccp_segmentation;
697 static int ett_sccp_ansi_isni_routing_control;
698 static int ett_sccp_xudt_msg_fragment;
699 static int ett_sccp_xudt_msg_fragments;
700 static int ett_sccp_assoc;
702 static expert_field ei_sccp_wrong_length;
703 static expert_field ei_sccp_international_standard_address;
704 static expert_field ei_sccp_no_ssn_present;
705 static expert_field ei_sccp_ssn_zero;
706 static expert_field ei_sccp_class_unexpected;
707 static expert_field ei_sccp_handling_invalid;
708 static expert_field ei_sccp_gt_digits_missing;
709 static expert_field ei_sccp_externally_reassembled;
712 static bool sccp_reassemble = true;
713 static bool show_key_params;
714 static bool set_addresses;
715 static bool dt1_ignore_length;
717 static int ss7pc_address_type = -1;
719 static int sccp_tap;
722 static const fragment_items sccp_xudt_msg_frag_items = {
723 /* Fragment subtrees */
724 &ett_sccp_xudt_msg_fragment,
725 &ett_sccp_xudt_msg_fragments,
726 /* Fragment fields */
727 &hf_sccp_xudt_msg_fragments,
728 &hf_sccp_xudt_msg_fragment,
729 &hf_sccp_xudt_msg_fragment_overlap,
730 &hf_sccp_xudt_msg_fragment_overlap_conflicts,
731 &hf_sccp_xudt_msg_fragment_multiple_tails,
732 &hf_sccp_xudt_msg_fragment_too_long_fragment,
733 &hf_sccp_xudt_msg_fragment_error,
734 &hf_sccp_xudt_msg_fragment_count,
735 /* Reassembled in field */
736 &hf_sccp_xudt_msg_reassembled_in,
737 /* Reassembled length field */
738 &hf_sccp_xudt_msg_reassembled_length,
739 /* Reassembled data field */
740 NULL,
741 /* Tag */
742 "SCCP XUDT Message fragments"
745 static reassembly_table sccp_xudt_msg_reassembly_table;
748 #define SCCP_USER_DATA 0
749 #define SCCP_USER_TCAP 1
750 #define SCCP_USER_RANAP 2
751 #define SCCP_USER_BSSAP 3
752 #define SCCP_USER_GSMMAP 4
753 #define SCCP_USER_CAMEL 5
754 #define SCCP_USER_INAP 6
755 #define SCCP_USER_BSAP 7
756 #define SCCP_USER_BSSAP_LE 8
757 #define SCCP_USER_BSSAP_PLUS 9
759 typedef struct _sccp_user_t {
760 unsigned ni;
761 range_t *called_pc;
762 range_t *called_ssn;
763 unsigned user;
764 bool uses_tcap;
765 dissector_handle_t *handlep;
766 } sccp_user_t;
768 static sccp_user_t *sccp_users;
769 static unsigned num_sccp_users;
771 static dissector_handle_t sccp_handle;
772 static dissector_handle_t data_handle;
773 static dissector_handle_t tcap_handle;
774 static dissector_handle_t ranap_handle;
775 static dissector_handle_t bssap_handle;
776 static dissector_handle_t gsmmap_handle;
777 static dissector_handle_t camel_handle;
778 static dissector_handle_t inap_handle;
779 static dissector_handle_t bsap_handle;
780 static dissector_handle_t bssap_le_handle;
781 static dissector_handle_t bssap_plus_handle;
782 static dissector_handle_t default_handle;
784 static const char *default_payload;
786 static const value_string sccp_users_vals[] = {
787 { SCCP_USER_DATA, "Data"},
788 { SCCP_USER_TCAP, "TCAP"},
789 { SCCP_USER_RANAP, "RANAP"},
790 { SCCP_USER_BSSAP, "BSSAP"},
791 { SCCP_USER_GSMMAP, "GSM MAP"},
792 { SCCP_USER_CAMEL, "CAMEL"},
793 { SCCP_USER_INAP, "INAP"},
794 { SCCP_USER_BSAP, "BSAP"},
795 { SCCP_USER_BSSAP_LE, "BSSAP-LE"},
796 { SCCP_USER_BSSAP_PLUS, "BSSAP+"},
797 { 0, NULL }
801 * Here are the global variables associated with
802 * the various user definable characteristics of the dissection
804 static uint32_t sccp_source_pc_global;
805 static bool sccp_show_length;
806 static bool trace_sccp;
808 static heur_dissector_list_t heur_subdissector_list;
810 static dissector_table_t sccp_ssn_dissector_table;
812 static wmem_tree_t *assocs;
813 static sccp_assoc_info_t no_assoc = { 0,0,0,INVALID_SSN,INVALID_SSN,false,false,NULL,NULL,SCCP_PLOAD_NONE,NULL,NULL,NULL, NULL, 0 };
814 static uint32_t next_assoc_id;
816 static const value_string assoc_protos[] = {
817 { SCCP_PLOAD_BSSAP, "BSSAP" },
818 { SCCP_PLOAD_RANAP, "RANAP" },
819 { 0, NULL }
823 * Fragment reassembly helpers.
825 * SCCP data can span multiple messages. As the same local reference number is
826 * used throughout a connection, this identifier is not sufficient for
827 * identifying reassembled PDUs with multiple fragments in the same frame. For
828 * that reason, create a new identifier for each group of fragments based on the
829 * more-data indicator (M-bit) and use that in place of the local reference
830 * number.
832 * As an optimization, if fragments do not need reassembly (a single message
833 * with the M-bit set), then no surrogate ID is needed nor stored since
834 * reassembly is skipped.
836 static uint32_t sccp_reassembly_id_next;
838 /* Maps a key to the current identifier as used in the reassembly API (first pass only). */
839 static wmem_tree_t *sccp_reassembly_ids;
841 /* Maps (frame number, offset) to a reassembly API identifier. */
842 static wmem_map_t *sccp_reassembly_id_map;
844 static uint32_t
845 sccp_reassembly_get_id_pass1(uint32_t frame, uint32_t offset, uint32_t key, bool more_frags)
847 uint32_t id = GPOINTER_TO_UINT(wmem_tree_lookup32(sccp_reassembly_ids, key));
848 if (!id) {
849 if (!more_frags) {
850 /* This is the last and only fragment, no need to reassembly anything. */
851 return 0;
854 /* This is a new fragment and "local reference", so create a new one. */
855 id = sccp_reassembly_id_next++;
856 wmem_tree_insert32(sccp_reassembly_ids, key, GUINT_TO_POINTER(id));
858 /* Save ID for second pass. */
859 uint64_t *frame_offset = wmem_new(wmem_file_scope(), uint64_t);
860 *frame_offset = ((uint64_t)offset << 32) | frame;
861 wmem_map_insert(sccp_reassembly_id_map, frame_offset, GUINT_TO_POINTER(id));
862 return id;
865 static uint32_t
866 sccp_reassembly_get_id_pass2(uint32_t frame, uint32_t offset)
868 uint64_t frame_offset = ((uint64_t)offset << 32) | frame;
869 return GPOINTER_TO_UINT(wmem_map_lookup(sccp_reassembly_id_map, &frame_offset));
873 * Returns the reassembly ID for the given frame at the given position or 0 if
874 * reassembly is not necessary.
876 static uint32_t
877 sccp_reassembly_get_id(packet_info *pinfo, uint32_t offset, uint32_t key, bool more_frags)
879 if (!PINFO_FD_VISITED(pinfo)) {
880 return sccp_reassembly_get_id_pass1(pinfo->num, offset, key, more_frags);
881 } else {
882 return sccp_reassembly_get_id_pass2(pinfo->num, offset);
886 static tvbuff_t *
887 sccp_reassemble_fragments(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
888 uint16_t length_offset, uint32_t source_local_ref, bool more_frags)
890 bool save_fragmented;
891 tvbuff_t *new_tvb;
892 fragment_head *frag_msg = NULL;
893 unsigned fragment_len;
894 uint32_t abs_offset, frags_id;
896 fragment_len = tvb_get_uint8(tvb, length_offset);
897 /* Assume that the absolute offset within the tvb uniquely identifies the
898 * message in this frame. */
899 abs_offset = tvb_raw_offset(tvb) + length_offset;
900 frags_id = sccp_reassembly_get_id(pinfo, abs_offset, source_local_ref, more_frags);
901 if (frags_id) {
903 * This fragment is part of multiple fragments, reassembly is required.
905 save_fragmented = pinfo->fragmented;
906 pinfo->fragmented = true;
907 frag_msg = fragment_add_seq_next(&sccp_xudt_msg_reassembly_table,
908 tvb, length_offset + 1,
909 pinfo,
910 frags_id, /* ID for fragments belonging together */
911 NULL,
912 fragment_len, /* fragment length - to the end */
913 more_frags); /* More fragments? */
915 if (!PINFO_FD_VISITED(pinfo) && frag_msg) {
916 /* Reassembly has finished, ensure that the next fragment gets a new ID. */
917 wmem_tree_remove32(sccp_reassembly_ids, source_local_ref);
920 new_tvb = process_reassembled_data(tvb, length_offset + 1, pinfo,
921 "Reassembled SCCP", frag_msg,
922 &sccp_xudt_msg_frag_items,
923 NULL, tree);
924 if (frag_msg) { /* Reassembled */
925 col_append_str(pinfo->cinfo, COL_INFO, "(Message reassembled) ");
926 } else { /* Not last packet of reassembled message */
927 col_append_str(pinfo->cinfo, COL_INFO, "(Message fragment) ");
929 pinfo->fragmented = save_fragmented;
930 } else {
932 * There is only a single fragment, reassembly is not required.
934 new_tvb = tvb_new_subset_length(tvb, length_offset + 1, fragment_len);
936 return new_tvb;
940 #define is_connectionless(m) \
941 ( m == SCCP_MSG_TYPE_UDT || m == SCCP_MSG_TYPE_UDTS \
942 || m == SCCP_MSG_TYPE_XUDT|| m == SCCP_MSG_TYPE_XUDTS \
943 || m == SCCP_MSG_TYPE_LUDT|| m == SCCP_MSG_TYPE_LUDTS)
945 #define RETURN_FALSE \
946 do { \
947 /*ws_warning("Frame %d not protocol %d @ line %d", frame_num, my_mtp3_standard, __LINE__);*/ \
948 return false; \
949 } while (0)
952 static void sccp_prompt(packet_info *pinfo _U_, char* result)
954 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Dissect SSN %d as",
955 GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_sccp, 0)));
958 static void *sccp_value(packet_info *pinfo)
960 return p_get_proto_data(pinfo->pool, pinfo, proto_sccp, 0);
963 static bool
964 sccp_called_calling_looks_valid(uint32_t frame_num _U_, tvbuff_t *tvb, uint8_t my_mtp3_standard, bool is_co)
966 uint8_t ai, ri, gti, ssni, pci;
967 uint8_t len_needed = 1; /* need at least the Address Indicator */
968 unsigned len = tvb_reported_length(tvb);
970 ai = tvb_get_uint8(tvb, 0);
971 if ((my_mtp3_standard == ANSI_STANDARD) && ((ai & ANSI_NATIONAL_MASK) == 0))
972 RETURN_FALSE;
974 gti = (ai & GTI_MASK) >> GTI_SHIFT;
975 if (my_mtp3_standard == ANSI_STANDARD) {
976 if (gti > 2)
977 RETURN_FALSE;
978 } else {
979 if (gti > 4)
980 RETURN_FALSE;
983 ri = (ai & ROUTING_INDICATOR_MASK) >> ROUTING_INDICATOR_SHIFT;
984 if (my_mtp3_standard == ANSI_STANDARD) {
985 pci = ai & ANSI_PC_INDICATOR_MASK;
986 ssni = ai & ANSI_SSN_INDICATOR_MASK;
987 } else {
988 ssni = ai & ITU_SSN_INDICATOR_MASK;
989 pci = ai & ITU_PC_INDICATOR_MASK;
992 /* Route on SSN with no SSN? */
993 if ((ri == ROUTE_ON_SSN) && (ssni == 0))
994 RETURN_FALSE;
996 /* Route on GT with no GT? */
997 if ((ri == ROUTE_ON_GT) && (gti == AI_GTI_NO_GT))
998 RETURN_FALSE;
1000 /* GT routed and connection-oriented (Class-2)?
1001 * Yes, that's theoretically possible, but it's not used.
1003 if ((ri == ROUTE_ON_GT) && is_co)
1004 RETURN_FALSE;
1006 if (ssni)
1007 len_needed += ADDRESS_SSN_LENGTH;
1008 if (pci) {
1009 if (my_mtp3_standard == ANSI_STANDARD ||
1010 my_mtp3_standard == CHINESE_ITU_STANDARD)
1011 len_needed += ANSI_PC_LENGTH;
1012 else
1013 len_needed += ITU_PC_LENGTH;
1015 if (gti)
1016 len_needed += 2;
1018 if (len_needed > len)
1019 RETURN_FALSE;
1021 return true;
1024 bool
1025 looks_like_valid_sccp(uint32_t frame_num _U_, tvbuff_t *tvb, uint8_t my_mtp3_standard)
1027 unsigned offset;
1028 uint8_t msgtype, msg_class, cause;
1029 unsigned called_ptr = 0;
1030 unsigned calling_ptr = 0;
1031 unsigned data_ptr = 0;
1032 unsigned opt_ptr = 0;
1033 uint8_t pointer_length = POINTER_LENGTH;
1034 unsigned len = tvb_captured_length(tvb);
1036 /* Ensure we can do some basic checks without throwing an exception.
1037 * Accesses beyond this length need to check the length first because
1038 * we don't want to throw an exception in here...
1040 if (len < 5)
1041 RETURN_FALSE;
1043 msgtype = tvb_get_uint8(tvb, SCCP_MSG_TYPE_OFFSET);
1044 if (!try_val_to_str(msgtype, sccp_message_type_acro_values)) {
1045 RETURN_FALSE;
1047 offset = SCCP_MSG_TYPE_LENGTH;
1049 switch (msgtype) {
1050 case SCCP_MSG_TYPE_UDT:
1051 case SCCP_MSG_TYPE_XUDT:
1052 case SCCP_MSG_TYPE_LUDT:
1053 case SCCP_MSG_TYPE_UDTS:
1054 case SCCP_MSG_TYPE_XUDTS:
1055 case SCCP_MSG_TYPE_LUDTS:
1057 if (msgtype == SCCP_MSG_TYPE_XUDT || msgtype == SCCP_MSG_TYPE_XUDTS) {
1058 if (SCCP_MSG_TYPE_LENGTH +
1059 PROTOCOL_CLASS_LENGTH + /* or Cause for XUDTS */
1060 HOP_COUNTER_LENGTH +
1061 POINTER_LENGTH +
1062 POINTER_LENGTH +
1063 POINTER_LENGTH +
1064 POINTER_LENGTH > len)
1065 RETURN_FALSE;
1068 if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS) {
1069 if (SCCP_MSG_TYPE_LENGTH +
1070 PROTOCOL_CLASS_LENGTH + /* or Cause for LUDTS */
1071 HOP_COUNTER_LENGTH +
1072 POINTER_LENGTH_LONG +
1073 POINTER_LENGTH_LONG +
1074 POINTER_LENGTH_LONG +
1075 POINTER_LENGTH_LONG > len)
1076 RETURN_FALSE;
1078 pointer_length = POINTER_LENGTH_LONG;
1081 if (msgtype == SCCP_MSG_TYPE_UDT || msgtype == SCCP_MSG_TYPE_XUDT ||
1082 msgtype == SCCP_MSG_TYPE_LUDT) {
1084 msg_class = tvb_get_uint8(tvb, offset) & CLASS_CLASS_MASK;
1085 if (msg_class > 1)
1086 RETURN_FALSE;
1087 offset += PROTOCOL_CLASS_LENGTH;
1090 if (msgtype == SCCP_MSG_TYPE_XUDT || msgtype == SCCP_MSG_TYPE_LUDT)
1091 offset += HOP_COUNTER_LENGTH;
1093 if (msgtype == SCCP_MSG_TYPE_UDTS ||
1094 msgtype == SCCP_MSG_TYPE_XUDTS ||
1095 msgtype == SCCP_MSG_TYPE_LUDTS) {
1097 cause = tvb_get_uint8(tvb, offset);
1098 if (!try_val_to_str(cause, sccp_return_cause_values))
1099 RETURN_FALSE;
1100 offset += RETURN_CAUSE_LENGTH;
1103 if (msgtype == SCCP_MSG_TYPE_XUDTS || msgtype == SCCP_MSG_TYPE_LUDTS)
1104 offset += HOP_COUNTER_LENGTH;
1106 if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS)
1107 called_ptr = tvb_get_letohs(tvb, offset);
1108 else
1109 called_ptr = tvb_get_uint8(tvb, offset);
1110 if (called_ptr == 0) /* Mandatory variable parameters must be present */
1111 RETURN_FALSE;
1112 called_ptr += offset;
1113 offset += pointer_length;
1115 if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS)
1116 calling_ptr = tvb_get_letohs(tvb, offset);
1117 else
1118 calling_ptr = tvb_get_uint8(tvb, offset);
1119 if (calling_ptr == 0) /* Mandatory variable parameters must be present */
1120 RETURN_FALSE;
1121 calling_ptr += offset;
1122 offset += pointer_length;
1124 if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS)
1125 data_ptr = tvb_get_letohs(tvb, offset);
1126 else
1127 data_ptr = tvb_get_uint8(tvb, offset);
1128 if (data_ptr == 0) /* Mandatory variable parameters must be present */
1129 RETURN_FALSE;
1130 data_ptr += offset;
1131 offset += pointer_length;
1133 if (msgtype == SCCP_MSG_TYPE_XUDT || msgtype == SCCP_MSG_TYPE_XUDTS) {
1134 opt_ptr = tvb_get_uint8(tvb, offset);
1135 offset += POINTER_LENGTH;
1136 } else if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS) {
1137 opt_ptr = tvb_get_letohs(tvb, offset);
1138 offset += POINTER_LENGTH_LONG;
1141 if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS) {
1142 /* Long pointers count from the 2nd (MSB) octet of the pointer */
1143 called_ptr += 1;
1144 calling_ptr += 1;
1145 data_ptr += 1;
1146 if (opt_ptr)
1147 opt_ptr += 1;
1150 /* Check that the variable pointers are within bounds */
1151 if (called_ptr > len || calling_ptr > len || data_ptr > len)
1152 RETURN_FALSE;
1154 /* Check that the lengths of the variable parameters are within bounds */
1155 if (tvb_get_uint8(tvb, called_ptr)+called_ptr > len ||
1156 tvb_get_uint8(tvb, calling_ptr)+calling_ptr > len)
1157 RETURN_FALSE;
1158 if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS) {
1159 if (tvb_get_letohs(tvb, data_ptr)+data_ptr > len)
1160 RETURN_FALSE;
1161 } else {
1162 if (tvb_get_uint8(tvb, data_ptr)+data_ptr > len)
1163 RETURN_FALSE;
1166 break;
1167 case SCCP_MSG_TYPE_CR:
1169 if (len < SCCP_MSG_TYPE_LENGTH
1170 + DESTINATION_LOCAL_REFERENCE_LENGTH
1171 + PROTOCOL_CLASS_LENGTH
1172 + POINTER_LENGTH
1173 + POINTER_LENGTH)
1174 RETURN_FALSE;
1176 offset += DESTINATION_LOCAL_REFERENCE_LENGTH;
1178 /* Class is only the lower 4 bits, but the upper 4 bits are spare
1179 * in Class-2. Don't mask them off so the below comparison also
1180 * fails if any of those spare bits are set.
1182 msg_class = tvb_get_uint8(tvb, offset);
1183 if (msg_class != 2)
1184 RETURN_FALSE;
1186 offset += PROTOCOL_CLASS_LENGTH;
1187 data_ptr = tvb_get_uint8(tvb, offset);
1188 if (data_ptr == 0)
1189 RETURN_FALSE;
1191 offset += POINTER_LENGTH;
1192 opt_ptr = tvb_get_uint8(tvb, offset);
1193 if (opt_ptr == 0)
1194 RETURN_FALSE;
1196 offset += POINTER_LENGTH;
1198 break;
1199 case SCCP_MSG_TYPE_CC:
1201 if (len < SCCP_MSG_TYPE_LENGTH
1202 + DESTINATION_LOCAL_REFERENCE_LENGTH
1203 + SOURCE_LOCAL_REFERENCE_LENGTH
1204 + PROTOCOL_CLASS_LENGTH
1205 + POINTER_LENGTH)
1206 RETURN_FALSE;
1208 offset += DESTINATION_LOCAL_REFERENCE_LENGTH;
1209 offset += SOURCE_LOCAL_REFERENCE_LENGTH;
1211 /* Class is only the lower 4 bits, but the upper 4 bits are spare
1212 * in Class-2. Don't mask them off so the below comparison also
1213 * fails if any of those spare bits are set.
1215 msg_class = tvb_get_uint8(tvb, offset);
1216 if (msg_class != 2)
1217 RETURN_FALSE;
1218 offset += PROTOCOL_CLASS_LENGTH;
1220 opt_ptr = tvb_get_uint8(tvb, offset);
1221 offset += POINTER_LENGTH;
1223 /* If the pointer isn't 0 (no optional parameters) or 1 (optional
1224 * parameter starts immediately after the pointer) then what would
1225 * be between the pointer and the parameter?
1227 if (opt_ptr > 1)
1228 RETURN_FALSE;
1230 /* If there are no optional parameters, are we at the end of the
1231 * message?
1233 if ((opt_ptr == 0) && (offset != len))
1234 RETURN_FALSE;
1236 break;
1237 case SCCP_MSG_TYPE_CREF:
1239 if (len < SCCP_MSG_TYPE_LENGTH
1240 + DESTINATION_LOCAL_REFERENCE_LENGTH
1241 + REFUSAL_CAUSE_LENGTH
1242 + POINTER_LENGTH)
1243 RETURN_FALSE;
1245 offset += DESTINATION_LOCAL_REFERENCE_LENGTH;
1247 cause = tvb_get_uint8(tvb, offset);
1248 if (!try_val_to_str(cause, sccp_refusal_cause_values))
1249 RETURN_FALSE;
1250 offset += REFUSAL_CAUSE_LENGTH;
1252 opt_ptr = tvb_get_uint8(tvb, offset);
1253 offset += POINTER_LENGTH;
1255 /* If the pointer isn't 0 (no optional parameters) or 1 (optional
1256 * parameter starts immediately after the pointer) then what would
1257 * be between the pointer and the parameter?
1259 if (opt_ptr > 1)
1260 RETURN_FALSE;
1262 /* If there are no optional parameters, are we at the end of the
1263 * message?
1265 if ((opt_ptr == 0) && (offset != len))
1266 RETURN_FALSE;
1268 break;
1269 case SCCP_MSG_TYPE_RLSD:
1271 if (len < SCCP_MSG_TYPE_LENGTH
1272 + DESTINATION_LOCAL_REFERENCE_LENGTH
1273 + SOURCE_LOCAL_REFERENCE_LENGTH
1274 + RELEASE_CAUSE_LENGTH
1275 + POINTER_LENGTH)
1276 RETURN_FALSE;
1278 offset += DESTINATION_LOCAL_REFERENCE_LENGTH;
1279 offset += SOURCE_LOCAL_REFERENCE_LENGTH;
1281 cause = tvb_get_uint8(tvb, offset);
1282 if (!try_val_to_str(cause, sccp_release_cause_values))
1283 RETURN_FALSE;
1284 offset += RELEASE_CAUSE_LENGTH;
1286 opt_ptr = tvb_get_uint8(tvb, offset);
1287 offset += POINTER_LENGTH;
1289 /* If the pointer isn't 0 (no optional parameters) or 1 (optional
1290 * parameter starts immediately after the pointer) then what would
1291 * be between the pointer and the parameter?
1293 if (opt_ptr > 1)
1294 RETURN_FALSE;
1296 /* If there are no optional parameters, are we at the end of the
1297 * message?
1299 if ((opt_ptr == 0) && (offset != len))
1300 RETURN_FALSE;
1302 break;
1303 case SCCP_MSG_TYPE_RLC:
1305 if (len != SCCP_MSG_TYPE_LENGTH
1306 + DESTINATION_LOCAL_REFERENCE_LENGTH
1307 + SOURCE_LOCAL_REFERENCE_LENGTH)
1308 RETURN_FALSE;
1310 break;
1311 case SCCP_MSG_TYPE_ERR:
1313 if (len != SCCP_MSG_TYPE_LENGTH
1314 + DESTINATION_LOCAL_REFERENCE_LENGTH
1315 + ERROR_CAUSE_LENGTH)
1316 RETURN_FALSE;
1318 offset += DESTINATION_LOCAL_REFERENCE_LENGTH;
1320 cause = tvb_get_uint8(tvb, offset);
1321 if (!try_val_to_str(cause, sccp_error_cause_values))
1322 RETURN_FALSE;
1324 break;
1325 case SCCP_MSG_TYPE_DT1:
1327 if (len < SCCP_MSG_TYPE_LENGTH
1328 + DESTINATION_LOCAL_REFERENCE_LENGTH
1329 + SEGMENTING_REASSEMBLING_LENGTH
1330 + POINTER_LENGTH
1331 + PARAMETER_LENGTH_LENGTH
1332 + 1) /* At least 1 byte of payload */
1333 RETURN_FALSE;
1334 offset += DESTINATION_LOCAL_REFERENCE_LENGTH;
1336 /* Are any of the spare bits in set? */
1337 if (tvb_get_uint8(tvb, offset) & ~SEGMENTING_REASSEMBLING_MASK)
1338 RETURN_FALSE;
1339 offset += SEGMENTING_REASSEMBLING_LENGTH;
1341 data_ptr = tvb_get_uint8(tvb, offset) + offset;
1342 /* Verify the data pointer is within bounds */
1343 if (data_ptr > len)
1344 RETURN_FALSE;
1345 offset += POINTER_LENGTH;
1347 /* Verify the data length uses the rest of the message */
1348 if (tvb_get_uint8(tvb, data_ptr) + offset + 1U != len)
1349 RETURN_FALSE;
1351 break;
1352 case SCCP_MSG_TYPE_IT:
1354 if (len < SCCP_MSG_TYPE_LENGTH
1355 + DESTINATION_LOCAL_REFERENCE_LENGTH
1356 + SOURCE_LOCAL_REFERENCE_LENGTH
1357 + PROTOCOL_CLASS_LENGTH
1358 + SEQUENCING_SEGMENTING_LENGTH
1359 + CREDIT_LENGTH)
1360 RETURN_FALSE;
1362 offset += DESTINATION_LOCAL_REFERENCE_LENGTH;
1363 offset += SOURCE_LOCAL_REFERENCE_LENGTH;
1365 /* Class is only the lower 4 bits, but the upper 4 bits are spare
1366 * in Class-2. Don't mask them off so the below comparison also
1367 * fails if any of those spare bits are set.
1369 msg_class = tvb_get_uint8(tvb, offset);
1370 if (msg_class != 2)
1371 RETURN_FALSE;
1372 offset += PROTOCOL_CLASS_LENGTH;
1374 break;
1375 case SCCP_MSG_TYPE_AK:
1376 case SCCP_MSG_TYPE_DT2:
1377 case SCCP_MSG_TYPE_EA:
1378 case SCCP_MSG_TYPE_ED:
1379 case SCCP_MSG_TYPE_RSC:
1380 case SCCP_MSG_TYPE_RSR:
1381 /* Class-3 is never actually used in the real world */
1382 RETURN_FALSE;
1383 break;
1385 default:
1386 DISSECTOR_ASSERT_NOT_REACHED();
1389 if (called_ptr) {
1390 uint8_t param_len = tvb_get_uint8(tvb, called_ptr);
1391 tvbuff_t *param_tvb;
1393 if (param_len == 0)
1394 RETURN_FALSE;
1395 param_tvb = tvb_new_subset_length(tvb, called_ptr+1, param_len);
1397 if (!sccp_called_calling_looks_valid(frame_num, param_tvb, my_mtp3_standard, !is_connectionless(msgtype)))
1398 RETURN_FALSE;
1401 if (calling_ptr) {
1402 uint8_t param_len = tvb_get_uint8(tvb, calling_ptr);
1403 tvbuff_t *param_tvb;
1405 if (param_len == 0)
1406 RETURN_FALSE;
1407 param_tvb = tvb_new_subset_length(tvb, calling_ptr+1, param_len);
1409 if (!sccp_called_calling_looks_valid(frame_num, param_tvb, my_mtp3_standard, !is_connectionless(msgtype)))
1410 RETURN_FALSE;
1413 if (opt_ptr) {
1414 uint8_t opt_param;
1416 opt_ptr += offset-pointer_length; /* (offset was already incremented) */
1418 /* Check that the optional pointer is within bounds */
1419 if (opt_ptr > len)
1420 RETURN_FALSE;
1422 opt_param = tvb_get_uint8(tvb, opt_ptr);
1423 /* Check if the (1st) optional parameter tag is valid */
1424 if (!try_val_to_str(opt_param, sccp_parameter_values))
1425 RETURN_FALSE;
1427 /* Check that the (1st) parameter length is within bounds */
1428 if ((opt_param != PARAMETER_END_OF_OPTIONAL_PARAMETERS) &&
1429 ((opt_ptr+1U) <= len) &&
1430 ((tvb_get_uint8(tvb, opt_ptr+1U)+offset) > len))
1431 RETURN_FALSE;
1433 /* If we're at the end of the parameters, are we also at the end of the
1434 * message?
1436 if ((opt_param == PARAMETER_END_OF_OPTIONAL_PARAMETERS) && ((opt_ptr+1U) != len))
1437 RETURN_FALSE;
1440 return true;
1443 static sccp_assoc_info_t *
1444 new_assoc(uint32_t calling, uint32_t called)
1446 sccp_assoc_info_t *a = wmem_new0(wmem_file_scope(), sccp_assoc_info_t);
1448 a->id = next_assoc_id++;
1449 a->calling_dpc = calling;
1450 a->called_dpc = called;
1451 a->calling_ssn = INVALID_SSN;
1452 a->called_ssn = INVALID_SSN;
1453 a->msgs = NULL;
1454 a->curr_msg = NULL;
1455 a->payload = SCCP_PLOAD_NONE;
1456 a->calling_party = NULL;
1457 a->called_party = NULL;
1458 a->extra_info = NULL;
1459 a->imsi = NULL;
1461 return a;
1464 sccp_assoc_info_t *
1465 get_sccp_assoc(packet_info *pinfo, unsigned offset, sccp_decode_context_t* value)
1467 uint32_t opck, dpck;
1468 address *opc = &(pinfo->src);
1469 address *dpc = &(pinfo->dst);
1470 unsigned framenum = pinfo->num;
1472 if (value->assoc)
1473 return value->assoc;
1475 opck = opc->type == ss7pc_address_type ? mtp3_pc_hash((const mtp3_addr_pc_t *)opc->data) : g_str_hash(address_to_str(pinfo->pool, opc));
1476 dpck = dpc->type == ss7pc_address_type ? mtp3_pc_hash((const mtp3_addr_pc_t *)dpc->data) : g_str_hash(address_to_str(pinfo->pool, dpc));
1479 switch (value->message_type) {
1480 case SCCP_MSG_TYPE_CR:
1482 /* CR contains the opc,dpc,dlr key of backward messages swapped as dpc,opc,slr */
1483 wmem_tree_key_t bw_key[4];
1485 bw_key[0].length = 1;
1486 bw_key[0].key = &dpck;
1488 bw_key[1].length = 1;
1489 bw_key[1].key = &opck;
1491 bw_key[2].length = 1;
1492 bw_key[2].key = &value->slr;
1494 bw_key[3].length = 0;
1495 bw_key[3].key = NULL;
1497 if (! (value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, bw_key) ) && ! PINFO_FD_VISITED(pinfo) ) {
1498 value->assoc = new_assoc(opck, dpck);
1499 wmem_tree_insert32_array(assocs, bw_key, value->assoc);
1500 value->assoc->has_bw_key = true;
1503 pinfo->p2p_dir = P2P_DIR_SENT;
1505 break;
1507 case SCCP_MSG_TYPE_CC:
1509 wmem_tree_key_t fw_key[4];
1510 wmem_tree_key_t bw_key[4];
1512 fw_key[0].length = 1;
1513 fw_key[0].key = &dpck;
1515 fw_key[1].length = 1;
1516 fw_key[1].key = &opck;
1518 fw_key[2].length = 1;
1519 fw_key[2].key = &value->slr;
1521 fw_key[3].length = 0;
1522 fw_key[3].key = NULL;
1524 bw_key[0].length = 1;
1525 bw_key[0].key = &opck;
1527 bw_key[1].length = 1;
1528 bw_key[1].key = &dpck;
1530 bw_key[2].length = 1;
1531 bw_key[2].key = &value->dlr;
1533 bw_key[3].length = 0;
1534 bw_key[3].key = NULL;
1537 if ( (value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, bw_key) ) ) {
1538 goto got_assoc;
1541 if ( (value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, fw_key) ) ) {
1542 goto got_assoc;
1545 value->assoc = new_assoc(dpck, opck);
1547 got_assoc:
1549 pinfo->p2p_dir = P2P_DIR_RECV;
1551 if ( ! PINFO_FD_VISITED(pinfo) && ! value->assoc->has_bw_key ) {
1552 wmem_tree_insert32_array(assocs, bw_key, value->assoc);
1553 value->assoc->has_bw_key = true;
1556 if ( ! PINFO_FD_VISITED(pinfo) && ! value->assoc->has_fw_key ) {
1557 wmem_tree_insert32_array(assocs, fw_key, value->assoc);
1558 value->assoc->has_fw_key = true;
1561 break;
1563 case SCCP_MSG_TYPE_IT:
1564 /* fall-through */
1565 case SCCP_MSG_TYPE_RLC:
1567 wmem_tree_key_t fw_key[4];
1568 wmem_tree_key_t bw_key[4];
1570 fw_key[0].length = 1;
1571 fw_key[0].key = &dpck;
1573 fw_key[1].length = 1;
1574 fw_key[1].key = &opck;
1576 fw_key[2].length = 1;
1577 fw_key[2].key = &value->slr;
1579 fw_key[3].length = 0;
1580 fw_key[3].key = NULL;
1582 bw_key[0].length = 1;
1583 bw_key[0].key = &opck;
1585 bw_key[1].length = 1;
1586 bw_key[1].key = &dpck;
1588 bw_key[2].length = 1;
1589 bw_key[2].key = &value->dlr;
1591 bw_key[3].length = 0;
1592 bw_key[3].key = NULL;
1594 if ( (value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, bw_key) ) ) {
1595 goto got_assoc_rlc;
1598 if ( (value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, fw_key) ) ) {
1599 goto got_assoc_rlc;
1602 value->assoc = new_assoc(dpck, opck);
1604 got_assoc_rlc:
1606 pinfo->p2p_dir = P2P_DIR_SENT;
1608 if ( ! PINFO_FD_VISITED(pinfo) && ! value->assoc->has_bw_key ) {
1609 wmem_tree_insert32_array(assocs, bw_key, value->assoc);
1610 value->assoc->has_bw_key = true;
1613 if ( ! PINFO_FD_VISITED(pinfo) && ! value->assoc->has_fw_key ) {
1614 wmem_tree_insert32_array(assocs, fw_key, value->assoc);
1615 value->assoc->has_fw_key = true;
1617 break;
1619 default:
1621 wmem_tree_key_t key[4];
1623 key[0].length = 1;
1624 key[0].key = &opck;
1626 key[1].length = 1;
1627 key[1].key = &dpck;
1629 key[2].length = 1;
1630 key[2].key = &value->dlr;
1632 key[3].length = 0;
1633 key[3].key = NULL;
1636 value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, key);
1638 if (value->assoc) {
1639 if (value->assoc->calling_dpc == dpck) {
1640 pinfo->p2p_dir = P2P_DIR_RECV;
1641 } else {
1642 pinfo->p2p_dir = P2P_DIR_SENT;
1646 break;
1650 if (value->assoc && trace_sccp) {
1651 if ( ! PINFO_FD_VISITED(pinfo)) {
1652 sccp_msg_info_t *msg = wmem_new0(wmem_file_scope(), sccp_msg_info_t);
1653 msg->framenum = framenum;
1654 msg->offset = offset;
1655 msg->data.co.next = NULL;
1656 msg->data.co.assoc = value->assoc;
1657 msg->data.co.label = NULL;
1658 msg->data.co.comment = NULL;
1659 msg->data.co.imsi = NULL;
1660 msg->type = value->message_type;
1662 if (value->assoc->msgs) {
1663 sccp_msg_info_t *m;
1664 for (m = value->assoc->msgs; m->data.co.next; m = m->data.co.next) ;
1665 m->data.co.next = msg;
1666 } else {
1667 value->assoc->msgs = msg;
1670 value->assoc->curr_msg = msg;
1672 } else {
1674 sccp_msg_info_t *m;
1676 for (m = value->assoc->msgs; m; m = m->data.co.next) {
1677 if (m->data.co.imsi != NULL && value->assoc->imsi == NULL) {
1678 value->assoc->imsi = wmem_strdup(wmem_epan_scope(), m->data.co.imsi);
1680 if ((m->framenum == framenum) && (m->offset == offset)) {
1681 value->assoc->curr_msg = m;
1682 break;
1688 return value->assoc ? value->assoc : &no_assoc;
1692 static void
1693 dissect_sccp_unknown_message(tvbuff_t *message_tvb, proto_tree *sccp_tree)
1695 uint32_t message_length;
1697 message_length = tvb_captured_length(message_tvb);
1699 proto_tree_add_bytes_format(sccp_tree, hf_sccp_unknown_message, message_tvb, 0, message_length,
1700 NULL, "Unknown message (%u byte%s)",
1701 message_length, plurality(message_length, "", "s"));
1704 static void
1705 dissect_sccp_unknown_param(tvbuff_t *tvb, proto_tree *tree, uint8_t type, unsigned length)
1707 proto_tree_add_bytes_format(tree, hf_sccp_unknown_parameter, tvb, 0, length, NULL,
1708 "Unknown parameter 0x%x (%u byte%s)", type, length, plurality(length, "", "s"));
1711 static void
1712 dissect_sccp_dlr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length, sccp_decode_context_t* sccp_info)
1714 proto_item *lr_item;
1716 if (length != 3) {
1717 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
1718 "Wrong length indicated. Expected 3, got %u", length);
1719 return;
1722 sccp_info->dlr = tvb_get_letoh24(tvb, 0);
1723 proto_tree_add_uint(tree, hf_sccp_dlr, tvb, 0, length, sccp_info->dlr);
1724 lr_item = proto_tree_add_uint(tree, hf_sccp_lr, tvb, 0, length, sccp_info->dlr);
1725 proto_item_set_generated(lr_item);
1727 if (show_key_params)
1728 col_append_fstr(pinfo->cinfo, COL_INFO, "DLR=%d ", sccp_info->dlr);
1731 static void
1732 dissect_sccp_slr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length, sccp_decode_context_t* sccp_info)
1734 proto_item *lr_item;
1736 if (length != 3) {
1737 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
1738 "Wrong length indicated. Expected 3, got %u", length);
1739 return;
1742 sccp_info->slr = tvb_get_letoh24(tvb, 0);
1743 proto_tree_add_uint(tree, hf_sccp_slr, tvb, 0, length, sccp_info->slr);
1744 lr_item = proto_tree_add_uint(tree, hf_sccp_lr, tvb, 0, length, sccp_info->slr);
1745 proto_item_set_generated(lr_item);
1747 if (show_key_params)
1748 col_append_fstr(pinfo->cinfo, COL_INFO, "SLR=%d ", sccp_info->slr);
1751 static proto_tree *
1752 dissect_sccp_gt_address_information(tvbuff_t *tvb, packet_info *pinfo,
1753 proto_tree *tree, unsigned length,
1754 bool even_length, bool called,
1755 sccp_decode_context_t* sccp_info)
1757 unsigned offset = 0;
1758 uint8_t odd_signal, even_signal;
1759 proto_item *digits_item;
1760 proto_tree *digits_tree;
1761 char *gt_digits;
1763 gt_digits = (char *)wmem_alloc0(pinfo->pool, GT_MAX_SIGNALS+1);
1765 while (offset < length) {
1766 odd_signal = tvb_get_uint8(tvb, offset) & GT_ODD_SIGNAL_MASK;
1767 even_signal = tvb_get_uint8(tvb, offset) & GT_EVEN_SIGNAL_MASK;
1768 even_signal >>= GT_EVEN_SIGNAL_SHIFT;
1770 (void) g_strlcat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values,
1771 "Unknown: %d"), GT_MAX_SIGNALS+1);
1773 /* If the last signal is NOT filler */
1774 if (offset != (length - 1) || even_length == true)
1775 (void) g_strlcat(gt_digits, val_to_str(even_signal, sccp_address_signal_values,
1776 "Unknown: %d"), GT_MAX_SIGNALS+1);
1778 offset += GT_SIGNAL_LENGTH;
1781 if (is_connectionless(sccp_info->message_type) && sccp_info->sccp_msg) {
1782 uint8_t **gt_ptr = called ? &(sccp_info->sccp_msg->data.ud.called_gt) : &(sccp_info->sccp_msg->data.ud.calling_gt);
1784 *gt_ptr = (uint8_t *)wmem_strdup(pinfo->pool, gt_digits);
1787 digits_item = proto_tree_add_string(tree, called ? hf_sccp_called_gt_digits
1788 : hf_sccp_calling_gt_digits,
1789 tvb, 0, length, gt_digits);
1790 digits_tree = proto_item_add_subtree(digits_item, called ? ett_sccp_called_gt_digits
1791 : ett_sccp_calling_gt_digits);
1793 if (set_addresses) {
1794 if (called) {
1795 set_address(&pinfo->dst, AT_STRINGZ, 1+(int)strlen(gt_digits), gt_digits);
1796 } else {
1797 set_address(&pinfo->src, AT_STRINGZ, 1+(int)strlen(gt_digits), gt_digits);
1801 proto_tree_add_string(digits_tree, hf_sccp_gt_digits, tvb, 0, length, gt_digits);
1802 proto_tree_add_uint(digits_tree, called ? hf_sccp_called_gt_digits_length
1803 : hf_sccp_calling_gt_digits_length,
1804 tvb, 0, length, (uint32_t)strlen(gt_digits));
1806 return digits_tree;
1809 static void
1810 dissect_sccp_global_title(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length,
1811 uint8_t gti, bool called, sccp_decode_context_t* sccp_info)
1813 proto_item *gt_item;
1814 proto_tree *gt_tree;
1815 proto_tree *digits_tree;
1816 tvbuff_t *signals_tvb;
1817 unsigned offset = 0;
1818 uint8_t odd_even, nai = 0, np = 0, es;
1819 bool even = true;
1821 /* Shift GTI to where we can work with it */
1822 gti >>= GTI_SHIFT;
1824 gt_tree = proto_tree_add_subtree_format(tree, tvb, offset, length,
1825 called ? ett_sccp_called_gt : ett_sccp_calling_gt, &gt_item,
1826 "Global Title 0x%x (%u byte%s)",
1827 gti, length, plurality(length,"", "s"));
1829 /* Decode Transaction Type (if present) */
1830 if ((gti == AI_GTI_TT) ||
1831 ((decode_mtp3_standard != ANSI_STANDARD) &&
1832 ((gti == ITU_AI_GTI_TT_NP_ES) || (gti == ITU_AI_GTI_TT_NP_ES_NAI))) ||
1833 ((decode_mtp3_standard == ANSI_STANDARD) && (gti == ANSI_AI_GTI_TT_NP_ES))) {
1835 proto_tree_add_item(gt_tree, called ? hf_sccp_called_gt_tt
1836 : hf_sccp_calling_gt_tt,
1837 tvb, offset, GT_TT_LENGTH, ENC_NA);
1838 offset += GT_TT_LENGTH;
1841 if (gti == AI_GTI_TT) {
1842 /* Protocol doesn't tell us, so we ASSUME even... */
1843 even = true;
1846 /* Decode Numbering Plan and Encoding Scheme (if present) */
1847 if (((decode_mtp3_standard != ANSI_STANDARD) &&
1848 ((gti == ITU_AI_GTI_TT_NP_ES) || (gti == ITU_AI_GTI_TT_NP_ES_NAI))) ||
1849 ((decode_mtp3_standard == ANSI_STANDARD) && (gti == ANSI_AI_GTI_TT_NP_ES))) {
1851 np = tvb_get_uint8(tvb, offset) & GT_NP_MASK;
1852 proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_np
1853 : hf_sccp_calling_gt_np,
1854 tvb, offset, GT_NP_ES_LENGTH, np);
1856 es = tvb_get_uint8(tvb, offset) & GT_ES_MASK;
1857 proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_es
1858 : hf_sccp_calling_gt_es,
1859 tvb, offset, GT_NP_ES_LENGTH, es);
1861 even = (es == GT_ES_BCD_EVEN) ? true : false;
1863 offset += GT_NP_ES_LENGTH;
1866 /* Decode Nature of Address Indicator (if present) */
1867 if ((decode_mtp3_standard != ANSI_STANDARD) &&
1868 ((gti == ITU_AI_GTI_NAI) || (gti == ITU_AI_GTI_TT_NP_ES_NAI))) {
1870 /* Decode Odd/Even Indicator (if present) */
1871 if (gti == ITU_AI_GTI_NAI) {
1872 odd_even = tvb_get_uint8(tvb, offset) & GT_OE_MASK;
1873 proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_oe
1874 : hf_sccp_calling_gt_oe,
1875 tvb, offset, GT_NAI_LENGTH, odd_even);
1876 even = (odd_even == GT_OE_EVEN) ? true : false;
1879 nai = tvb_get_uint8(tvb, offset) & GT_NAI_MASK;
1880 proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_nai
1881 : hf_sccp_calling_gt_nai,
1882 tvb, offset, GT_NAI_LENGTH, nai);
1884 offset += GT_NAI_LENGTH;
1887 if(length == 0){
1888 expert_add_info(pinfo, gt_item, &ei_sccp_gt_digits_missing);
1889 return;
1892 /* Decode address signal(s) */
1893 if (length < offset)
1894 return;
1896 signals_tvb = tvb_new_subset_length(tvb, offset, (length - offset));
1898 digits_tree = dissect_sccp_gt_address_information(signals_tvb, pinfo, gt_tree,
1899 (length - offset),
1900 even, called, sccp_info);
1902 /* Display the country code (if we can) */
1903 switch (np >> GT_NP_SHIFT) {
1904 case GT_NP_ISDN:
1905 case GT_NP_ISDN_MOBILE:
1906 if (nai == GT_NAI_INTERNATIONAL_NUM) {
1907 dissect_e164_cc(signals_tvb, digits_tree, 0, E164_ENC_BCD);
1909 break;
1910 case GT_NP_LAND_MOBILE:
1911 dissect_e212_mcc_mnc_in_address(signals_tvb, pinfo, digits_tree, 0);
1912 break;
1913 default:
1914 break;
1918 static int
1919 dissect_sccp_3byte_pc(tvbuff_t *tvb, proto_tree *call_tree, unsigned offset,
1920 bool called)
1922 int hf_pc;
1924 if (decode_mtp3_standard == ANSI_STANDARD)
1926 if (called)
1927 hf_pc = hf_sccp_called_ansi_pc;
1928 else
1929 hf_pc = hf_sccp_calling_ansi_pc;
1930 } else /* CHINESE_ITU_STANDARD */ {
1931 if (called)
1932 hf_pc = hf_sccp_called_chinese_pc;
1933 else
1934 hf_pc = hf_sccp_calling_chinese_pc;
1937 /* create and fill the PC tree */
1938 dissect_mtp3_3byte_pc(tvb, offset, call_tree,
1939 called ? ett_sccp_called_pc : ett_sccp_calling_pc,
1940 hf_pc,
1941 called ? hf_sccp_called_pc_network : hf_sccp_calling_pc_network,
1942 called ? hf_sccp_called_pc_cluster : hf_sccp_calling_pc_cluster,
1943 called ? hf_sccp_called_pc_member : hf_sccp_calling_pc_member,
1944 0, 0);
1946 return offset + ANSI_PC_LENGTH;
1949 /* FUNCTION dissect_sccp_called_calling_param():
1950 * Dissect the Calling or Called Party Address parameters.
1952 * The boolean 'called' describes whether this function is decoding a
1953 * called (true) or calling (false) party address. There is simply too
1954 * much code in this function to have 2 copies of it (one for called, one
1955 * for calling).
1957 * NOTE: this function is called even when (!tree) so that we can get
1958 * the SSN and subsequently call subdissectors (if and when there's a data
1959 * parameter). Realistically we should put if (!tree)'s around a lot of the
1960 * code, but I think that would make it unreadable--and the expense of not
1961 * doing so does not appear to be very high.
1963 static void
1964 dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
1965 unsigned length, bool called, sccp_decode_context_t* sccp_info)
1967 proto_item *call_ai_item, *item, *hidden_item, *expert_item;
1968 proto_tree *call_tree, *call_ai_tree;
1969 unsigned offset;
1970 uint8_t national = 0xFFU, routing_ind, gti, pci, ssni, ssn;
1971 tvbuff_t *gt_tvb;
1972 dissector_handle_t ssn_dissector = NULL, tcap_ssn_dissector = NULL;
1973 const char *ssn_dissector_description = NULL;
1974 const char *tcap_ssn_dissector_description = NULL;
1976 call_tree = proto_tree_add_subtree_format(tree, tvb, 0, length,
1977 called ? ett_sccp_called : ett_sccp_calling, NULL,
1978 "%s Party address (%u byte%s)",
1979 called ? "Called" : "Calling", length,
1980 plurality(length, "", "s"));
1982 call_ai_tree = proto_tree_add_subtree(call_tree, tvb, 0,
1983 ADDRESS_INDICATOR_LENGTH,
1984 called ? ett_sccp_called_ai : ett_sccp_calling_ai, &call_ai_item, "Address Indicator");
1986 if (decode_mtp3_standard == ANSI_STANDARD) {
1987 national = tvb_get_uint8(tvb, 0) & ANSI_NATIONAL_MASK;
1988 expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_national_indicator
1989 : hf_sccp_calling_ansi_national_indicator,
1990 tvb, 0, ADDRESS_INDICATOR_LENGTH, national);
1991 if (national == 0)
1992 expert_add_info(pinfo, expert_item, &ei_sccp_international_standard_address);
1993 } else {
1994 uint8_t natl_use_bit = tvb_get_uint8(tvb, 0) & ITU_RESERVED_MASK;
1996 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_natl_use_bit
1997 : hf_sccp_calling_itu_natl_use_bit,
1998 tvb, 0, ADDRESS_INDICATOR_LENGTH, natl_use_bit);
2001 routing_ind = tvb_get_uint8(tvb, 0) & ROUTING_INDICATOR_MASK;
2002 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_routing_indicator : hf_sccp_calling_routing_indicator,
2003 tvb, 0, ADDRESS_INDICATOR_LENGTH, routing_ind);
2004 /* Only shift off the other bits after adding the item */
2005 routing_ind >>= ROUTING_INDICATOR_SHIFT;
2007 gti = tvb_get_uint8(tvb, 0) & GTI_MASK;
2009 if (decode_mtp3_standard == ITU_STANDARD ||
2010 decode_mtp3_standard == CHINESE_ITU_STANDARD ||
2011 decode_mtp3_standard == JAPAN_STANDARD ||
2012 national == 0) {
2014 proto_tree_add_uint(call_ai_tree,
2015 called ? hf_sccp_called_itu_global_title_indicator : hf_sccp_calling_itu_global_title_indicator,
2016 tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
2018 ssni = tvb_get_uint8(tvb, 0) & ITU_SSN_INDICATOR_MASK;
2019 expert_item = proto_tree_add_uint(call_ai_tree,
2020 called ? hf_sccp_called_itu_ssn_indicator : hf_sccp_calling_itu_ssn_indicator,
2021 tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
2022 if ((routing_ind == ROUTE_ON_SSN) && (ssni == 0)) {
2023 expert_add_info(pinfo, expert_item, &ei_sccp_no_ssn_present);
2026 pci = tvb_get_uint8(tvb, 0) & ITU_PC_INDICATOR_MASK;
2027 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_point_code_indicator : hf_sccp_calling_itu_point_code_indicator,
2028 tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
2030 offset = ADDRESS_INDICATOR_LENGTH;
2032 /* Dissect PC (if present) */
2033 if (pci) {
2034 if (decode_mtp3_standard == ITU_STANDARD || national == 0) {
2035 if (length < offset + ITU_PC_LENGTH) {
2036 proto_tree_add_expert_format(call_tree, pinfo, &ei_sccp_wrong_length, tvb, 0, -1,
2037 "Wrong length indicated (%u) should be at least %u, PC is %u octets",
2038 length, offset + ITU_PC_LENGTH, ITU_PC_LENGTH);
2039 return;
2041 proto_tree_add_item(call_tree, called ? hf_sccp_called_itu_pc : hf_sccp_calling_itu_pc,
2042 tvb, offset, ITU_PC_LENGTH, ENC_LITTLE_ENDIAN);
2043 offset += ITU_PC_LENGTH;
2045 } else if (decode_mtp3_standard == JAPAN_STANDARD) {
2047 if (length < offset + JAPAN_PC_LENGTH) {
2048 proto_tree_add_expert_format(call_tree, pinfo, &ei_sccp_wrong_length, tvb, 0, -1,
2049 "Wrong length indicated (%u) should be at least %u, PC is %u octets",
2050 length, offset + JAPAN_PC_LENGTH, JAPAN_PC_LENGTH);
2051 return;
2053 proto_tree_add_item(call_tree, called ? hf_sccp_called_japan_pc : hf_sccp_calling_japan_pc,
2054 tvb, offset, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
2056 offset += JAPAN_PC_LENGTH;
2058 } else /* CHINESE_ITU_STANDARD */ {
2060 if (length < offset + ANSI_PC_LENGTH) {
2061 proto_tree_add_expert_format(call_tree, pinfo, &ei_sccp_wrong_length, tvb, 0, -1,
2062 "Wrong length indicated (%u) should be at least %u, PC is %u octets",
2063 length, offset + ANSI_PC_LENGTH, ANSI_PC_LENGTH);
2064 return;
2066 offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
2071 /* Dissect SSN (if present) */
2072 if (ssni) {
2073 ssn = tvb_get_uint8(tvb, offset);
2075 if ((routing_ind == ROUTE_ON_SSN) && (ssn == 0)) {
2076 expert_add_info(pinfo, expert_item, &ei_sccp_ssn_zero);
2079 if (called && sccp_info->assoc)
2080 sccp_info->assoc->called_ssn = ssn;
2081 else if (sccp_info->assoc)
2082 sccp_info->assoc->calling_ssn = ssn;
2084 if (is_connectionless(sccp_info->message_type) && sccp_info->sccp_msg) {
2085 unsigned *ssn_ptr = called ? &(sccp_info->sccp_msg->data.ud.called_ssn) : &(sccp_info->sccp_msg->data.ud.calling_ssn);
2087 *ssn_ptr = ssn;
2090 proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
2091 : hf_sccp_calling_ssn,
2092 tvb, offset, ADDRESS_SSN_LENGTH, ssn);
2093 hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset,
2094 ADDRESS_SSN_LENGTH, ssn);
2095 proto_item_set_hidden(hidden_item);
2097 offset += ADDRESS_SSN_LENGTH;
2099 /* Get the dissector handle of the dissector registered for this ssn
2100 * And print its name.
2102 ssn_dissector = dissector_get_uint_handle(sccp_ssn_dissector_table, ssn);
2104 if (ssn_dissector) {
2105 ssn_dissector_description = dissector_handle_get_description(ssn_dissector);
2107 if (ssn_dissector_description) {
2108 item = proto_tree_add_string_format(call_tree, hf_sccp_linked_dissector, tvb, offset - 1, ADDRESS_SSN_LENGTH,
2109 ssn_dissector_description, "Linked to %s", ssn_dissector_description);
2110 proto_item_set_generated(item);
2112 if (g_ascii_strncasecmp("TCAP", ssn_dissector_description, 4)== 0) {
2113 tcap_ssn_dissector = get_itu_tcap_subdissector(ssn);
2115 if (tcap_ssn_dissector) {
2116 tcap_ssn_dissector_description = dissector_handle_get_description(tcap_ssn_dissector);
2117 proto_item_append_text(item,", TCAP SSN linked to %s", tcap_ssn_dissector_description);
2120 } /* short name */
2121 } /* ssn_dissector */
2122 } /* ssni */
2124 /* Dissect GT (if present) */
2125 if (gti != AI_GTI_NO_GT) {
2126 if (length < offset)
2127 return;
2129 gt_tvb = tvb_new_subset_length(tvb, offset, (length - offset));
2130 dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti,
2131 called, sccp_info);
2134 } else if (decode_mtp3_standard == ANSI_STANDARD) {
2136 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_global_title_indicator
2137 : hf_sccp_calling_ansi_global_title_indicator,
2138 tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
2140 pci = tvb_get_uint8(tvb, 0) & ANSI_PC_INDICATOR_MASK;
2141 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_point_code_indicator
2142 : hf_sccp_calling_ansi_point_code_indicator,
2143 tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
2145 ssni = tvb_get_uint8(tvb, 0) & ANSI_SSN_INDICATOR_MASK;
2146 expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator
2147 : hf_sccp_calling_ansi_ssn_indicator,
2148 tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
2149 if ((routing_ind == ROUTE_ON_SSN) && (ssni == 0)) {
2150 expert_add_info(pinfo, expert_item, &ei_sccp_no_ssn_present);
2153 offset = ADDRESS_INDICATOR_LENGTH;
2155 /* Dissect SSN (if present) */
2156 if (ssni) {
2157 ssn = tvb_get_uint8(tvb, offset);
2159 if ((routing_ind == ROUTE_ON_SSN) && (ssn == 0)) {
2160 expert_add_info(pinfo, expert_item, &ei_sccp_ssn_zero);
2163 if (called && sccp_info->assoc) {
2164 sccp_info->assoc->called_ssn = ssn;
2165 } else if (sccp_info->assoc) {
2166 sccp_info->assoc->calling_ssn = ssn;
2169 if (is_connectionless(sccp_info->message_type) && sccp_info->sccp_msg) {
2170 unsigned *ssn_ptr = called ? &(sccp_info->sccp_msg->data.ud.called_ssn) : &(sccp_info->sccp_msg->data.ud.calling_ssn);
2172 *ssn_ptr = ssn;
2175 proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
2176 : hf_sccp_calling_ssn,
2177 tvb, offset, ADDRESS_SSN_LENGTH, ssn);
2178 hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset,
2179 ADDRESS_SSN_LENGTH, ssn);
2180 proto_item_set_hidden(hidden_item);
2182 offset += ADDRESS_SSN_LENGTH;
2185 /* Dissect PC (if present) */
2186 if (pci) {
2187 offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
2190 /* Dissect GT (if present) */
2191 if (gti != AI_GTI_NO_GT) {
2192 if (length < offset)
2193 return;
2194 gt_tvb = tvb_new_subset_length(tvb, offset, (length - offset));
2195 dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti,
2196 called, sccp_info);
2203 static void
2204 dissect_sccp_called_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length, sccp_decode_context_t* sccp_info)
2206 dissect_sccp_called_calling_param(tvb, tree, pinfo, length, true, sccp_info);
2209 static void
2210 dissect_sccp_calling_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length, sccp_decode_context_t* sccp_info)
2212 dissect_sccp_called_calling_param(tvb, tree, pinfo, length, false, sccp_info);
2215 static void
2216 dissect_sccp_class_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length, sccp_decode_context_t* sccp_info)
2218 uint8_t msg_class;
2219 proto_item *pi;
2220 bool invalid_class = false;
2222 if (length != 1) {
2223 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
2224 "Wrong length indicated. Expected 1, got %u", length);
2225 return;
2228 msg_class = tvb_get_uint8(tvb, 0) & CLASS_CLASS_MASK;
2229 pi = proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, msg_class);
2231 switch (sccp_info->message_type) {
2232 case SCCP_MSG_TYPE_DT1:
2233 if (msg_class != 2)
2234 invalid_class = true;
2235 break;
2236 case SCCP_MSG_TYPE_DT2:
2237 case SCCP_MSG_TYPE_AK:
2238 case SCCP_MSG_TYPE_ED:
2239 case SCCP_MSG_TYPE_EA:
2240 case SCCP_MSG_TYPE_RSR:
2241 case SCCP_MSG_TYPE_RSC:
2242 if (msg_class != 3)
2243 invalid_class = true;
2244 break;
2245 case SCCP_MSG_TYPE_CR:
2246 case SCCP_MSG_TYPE_CC:
2247 case SCCP_MSG_TYPE_CREF:
2248 case SCCP_MSG_TYPE_RLSD:
2249 case SCCP_MSG_TYPE_RLC:
2250 case SCCP_MSG_TYPE_ERR:
2251 case SCCP_MSG_TYPE_IT:
2252 if ((msg_class != 2) && (msg_class != 3))
2253 invalid_class = true;
2254 break;
2255 case SCCP_MSG_TYPE_UDT:
2256 case SCCP_MSG_TYPE_UDTS:
2257 case SCCP_MSG_TYPE_XUDT:
2258 case SCCP_MSG_TYPE_XUDTS:
2259 case SCCP_MSG_TYPE_LUDT:
2260 case SCCP_MSG_TYPE_LUDTS:
2261 if ((msg_class != 0) && (msg_class != 1))
2262 invalid_class = true;
2263 break;
2266 if (invalid_class)
2267 expert_add_info(pinfo, pi, &ei_sccp_class_unexpected);
2269 if (msg_class == 0 || msg_class == 1) {
2270 uint8_t handling = tvb_get_uint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK;
2272 pi = proto_tree_add_item(tree, hf_sccp_handling, tvb, 0, length, ENC_NA);
2273 handling >>= CLASS_SPARE_HANDLING_SHIFT;
2275 if (try_val_to_str(handling, sccp_class_handling_values) == NULL) {
2276 expert_add_info(pinfo, pi, &ei_sccp_handling_invalid);
2281 static void
2282 dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length)
2284 if (length != 1) {
2285 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
2286 "Wrong length indicated. Expected 1, got %u", length);
2287 return;
2290 proto_tree_add_item(tree, hf_sccp_more, tvb, 0, length, ENC_BIG_ENDIAN);
2293 static void
2294 dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length)
2296 if (length != 1) {
2297 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
2298 "Wrong length indicated. Expected 1, got %u", length);
2299 return;
2302 proto_tree_add_item(tree, hf_sccp_rsn, tvb, 0, length, ENC_NA);
2305 static void
2306 dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, unsigned length)
2308 proto_tree *param_tree;
2310 param_tree = proto_tree_add_subtree(tree, tvb, 0, length, ett_sccp_sequencing_segmenting, NULL,
2311 val_to_str(PARAMETER_SEQUENCING_SEGMENTING,
2312 sccp_parameter_values, "Unknown: %d"));
2314 proto_tree_add_item(param_tree, hf_sccp_sequencing_segmenting_ssn, tvb, 0,
2315 SEQUENCING_SEGMENTING_SSN_LENGTH, ENC_NA);
2316 proto_tree_add_item(param_tree, hf_sccp_sequencing_segmenting_rsn, tvb,
2317 SEQUENCING_SEGMENTING_SSN_LENGTH,
2318 SEQUENCING_SEGMENTING_RSN_LENGTH, ENC_NA);
2319 proto_tree_add_item(param_tree, hf_sccp_sequencing_segmenting_more, tvb,
2320 SEQUENCING_SEGMENTING_SSN_LENGTH,
2321 SEQUENCING_SEGMENTING_RSN_LENGTH, ENC_NA);
2324 static void
2325 dissect_sccp_credit_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length)
2327 if (length != 1) {
2328 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
2329 "Wrong length indicated. Expected 1, got %u", length);
2330 return;
2333 proto_tree_add_item(tree, hf_sccp_credit, tvb, 0, length, ENC_NA);
2336 static void
2337 dissect_sccp_release_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length)
2339 if (length != 1) {
2340 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
2341 "Wrong length indicated. Expected 1, got %u", length);
2342 return;
2345 proto_tree_add_item(tree, hf_sccp_release_cause, tvb, 0, length, ENC_LITTLE_ENDIAN);
2347 if (show_key_params)
2348 col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", tvb_get_uint8(tvb, 0));
2351 static void
2352 dissect_sccp_return_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length)
2354 if (length != 1) {
2355 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
2356 "Wrong length indicated. Expected 1, got %u", length);
2357 return;
2360 proto_tree_add_item(tree, hf_sccp_return_cause, tvb, 0, length, ENC_LITTLE_ENDIAN);
2362 if (show_key_params)
2363 col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", tvb_get_uint8(tvb, 0));
2366 static void
2367 dissect_sccp_reset_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length)
2369 if (length != 1) {
2370 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
2371 "Wrong length indicated. Expected 1, got %u", length);
2372 return;
2375 proto_tree_add_item(tree, hf_sccp_reset_cause, tvb, 0, length, ENC_LITTLE_ENDIAN);
2377 if (show_key_params)
2378 col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", tvb_get_uint8(tvb, 0));
2381 static void
2382 dissect_sccp_error_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length)
2384 if (length != 1) {
2385 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
2386 "Wrong length indicated. Expected 1, got %u", length);
2387 return;
2390 proto_tree_add_item(tree, hf_sccp_error_cause, tvb, 0, length, ENC_LITTLE_ENDIAN);
2392 if (show_key_params)
2393 col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", tvb_get_uint8(tvb, 0));
2396 static void
2397 dissect_sccp_refusal_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length)
2399 if (length != 1) {
2400 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
2401 "Wrong length indicated. Expected 1, got %u", length);
2402 return;
2405 proto_tree_add_item(tree, hf_sccp_refusal_cause, tvb, 0, length, ENC_LITTLE_ENDIAN);
2407 if (show_key_params)
2408 col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", tvb_get_uint8(tvb, 0));
2412 /* This function is used for both data and long data (ITU only) parameters */
2413 static void
2414 dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, sccp_assoc_info_t *assoc)
2416 uint8_t ssn = INVALID_SSN;
2417 uint8_t other_ssn = INVALID_SSN;
2418 const mtp3_addr_pc_t *dpc = NULL;
2419 const mtp3_addr_pc_t *opc = NULL;
2420 heur_dtbl_entry_t *hdtbl_entry;
2421 struct _sccp_msg_info_t* sccp_info = NULL;
2423 if ((trace_sccp) && (assoc && assoc != &no_assoc)) {
2424 sccp_info = assoc->curr_msg;
2427 if (assoc) {
2428 switch (pinfo->p2p_dir) {
2429 case P2P_DIR_SENT:
2430 ssn = assoc->calling_ssn;
2431 other_ssn = assoc->called_ssn;
2432 dpc = (const mtp3_addr_pc_t*)pinfo->dst.data;
2433 opc = (const mtp3_addr_pc_t*)pinfo->src.data;
2434 break;
2435 case P2P_DIR_RECV:
2436 ssn = assoc->called_ssn;
2437 other_ssn = assoc->calling_ssn;
2438 dpc = (const mtp3_addr_pc_t*)pinfo->src.data;
2439 opc = (const mtp3_addr_pc_t*)pinfo->dst.data;
2440 break;
2441 default:
2442 ssn = assoc->called_ssn;
2443 other_ssn = assoc->calling_ssn;
2444 dpc = (const mtp3_addr_pc_t*)pinfo->dst.data;
2445 opc = (const mtp3_addr_pc_t*)pinfo->src.data;
2446 break;
2451 if ((num_sccp_users) && (pinfo->src.type == ss7pc_address_type)) {
2452 unsigned i;
2453 dissector_handle_t handle = NULL;
2454 bool uses_tcap = false;
2456 for (i=0; i < num_sccp_users; i++) {
2457 sccp_user_t *u = &(sccp_users[i]);
2459 if (!dpc || dpc->ni != u->ni) continue;
2461 if (value_is_in_range(u->called_ssn, ssn) && value_is_in_range(u->called_pc, dpc->pc) ) {
2462 handle = *(u->handlep);
2463 uses_tcap = u->uses_tcap;
2464 break;
2465 } else if (value_is_in_range(u->called_ssn, other_ssn) && opc && value_is_in_range(u->called_pc, opc->pc) ) {
2466 handle = *(u->handlep);
2467 uses_tcap = u->uses_tcap;
2468 break;
2472 if (handle) {
2473 if (uses_tcap) {
2474 call_tcap_dissector(handle, tvb, pinfo, tree);
2475 } else {
2476 call_dissector_with_data(handle, tvb, pinfo, tree, sccp_info);
2478 return;
2483 /* Save SSN for Decode As */
2484 p_add_proto_data(pinfo->pool, pinfo, proto_sccp, 0, GUINT_TO_POINTER((unsigned)ssn));
2486 if ((ssn != INVALID_SSN) && dissector_try_uint_with_data(sccp_ssn_dissector_table, ssn, tvb, pinfo, tree, true, sccp_info)) {
2487 return;
2490 if ((other_ssn != INVALID_SSN) && dissector_try_uint_with_data(sccp_ssn_dissector_table, other_ssn, tvb, pinfo, tree, true, sccp_info)) {
2491 return;
2494 /* try heuristic subdissector list to see if there are any takers */
2495 if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, &hdtbl_entry, sccp_info)) {
2496 return;
2499 /* try user default subdissector */
2500 if (default_handle) {
2501 call_dissector_with_data(default_handle, tvb, pinfo, tree, sccp_info);
2502 return;
2505 /* No sub-dissection occurred, treat it as raw data */
2506 call_dissector(data_handle, tvb, pinfo, tree);
2510 static void
2511 dissect_sccp_segmentation_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length)
2513 proto_tree *param_tree;
2515 param_tree = proto_tree_add_subtree(tree, tvb, 0, length, ett_sccp_segmentation, NULL,
2516 val_to_str(PARAMETER_SEGMENTATION,
2517 sccp_parameter_values, "Unknown: %d"));
2519 proto_tree_add_item(param_tree, hf_sccp_segmentation_first, tvb, 0, 1, ENC_NA);
2520 proto_tree_add_item(param_tree, hf_sccp_segmentation_class, tvb, 0, 1, ENC_NA);
2521 proto_tree_add_item(param_tree, hf_sccp_segmentation_remaining, tvb, 0, 1, ENC_NA);
2523 if (length-1 != 3) {
2524 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length-1,
2525 "Wrong length indicated. Expected 3, got %u", length-1);
2526 return;
2529 proto_tree_add_item(param_tree, hf_sccp_segmentation_slr, tvb, 1, length-1, ENC_LITTLE_ENDIAN);
2532 static void
2533 dissect_sccp_hop_counter_param(tvbuff_t *tvb, proto_tree *tree, unsigned length)
2535 uint8_t hops;
2537 hops = tvb_get_uint8(tvb, 0);
2538 proto_tree_add_uint(tree, hf_sccp_hop_counter, tvb, 0, length, hops);
2541 static void
2542 dissect_sccp_importance_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length)
2544 if (length != 1) {
2545 proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length,
2546 "Wrong length indicated. Expected 1, got %u", length);
2547 return;
2550 proto_tree_add_item(tree, hf_sccp_importance, tvb, 0, length, ENC_NA);
2553 static void
2554 dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, unsigned length)
2556 uint8_t ti;
2557 unsigned offset = 0;
2558 proto_tree *param_tree;
2560 /* Create a subtree for ISNI Routing Control */
2561 param_tree = proto_tree_add_subtree(tree, tvb, offset, ANSI_ISNI_ROUTING_CONTROL_LENGTH,
2562 ett_sccp_ansi_isni_routing_control, NULL, "ISNI Routing Control");
2564 proto_tree_add_item(param_tree, hf_sccp_ansi_isni_mi, tvb, offset,
2565 ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA);
2567 proto_tree_add_item(param_tree, hf_sccp_ansi_isni_iri, tvb, offset,
2568 ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA);
2570 ti = tvb_get_uint8(tvb, offset) & ANSI_ISNI_TI_MASK;
2571 proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_ti, tvb, offset,
2572 ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
2574 proto_tree_add_item(param_tree, hf_sccp_ansi_isni_counter, tvb, offset,
2575 ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA);
2577 offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
2579 if ((ti >> ANSI_ISNI_TI_SHIFT) == ANSI_ISNI_TYPE_1) {
2580 proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_netspec, tvb, offset,
2581 ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
2582 offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
2585 while (offset < length) {
2587 proto_tree_add_item(tree, hf_sccp_ansi_isni_network, tvb, offset,
2588 ANSI_NCM_LENGTH, ENC_NA);
2589 offset++;
2591 proto_tree_add_item(tree, hf_sccp_ansi_isni_cluster, tvb, offset,
2592 ANSI_NCM_LENGTH, ENC_NA);
2593 offset++;
2598 /* FUNCTION dissect_sccp_parameter():
2599 * Dissect a parameter given its type, offset into tvb, and length.
2601 static uint16_t
2602 dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
2603 proto_tree *tree, uint8_t parameter_type, int offset,
2604 uint16_t parameter_length, sccp_decode_context_t *sccp_info)
2606 tvbuff_t *parameter_tvb;
2608 switch (parameter_type) {
2609 case PARAMETER_CALLED_PARTY_ADDRESS:
2610 case PARAMETER_CALLING_PARTY_ADDRESS:
2611 case PARAMETER_DATA:
2612 case PARAMETER_LONG_DATA:
2613 case PARAMETER_SOURCE_LOCAL_REFERENCE:
2614 case PARAMETER_DESTINATION_LOCAL_REFERENCE:
2615 case PARAMETER_RELEASE_CAUSE:
2616 case PARAMETER_RETURN_CAUSE:
2617 case PARAMETER_RESET_CAUSE:
2618 case PARAMETER_ERROR_CAUSE:
2619 case PARAMETER_REFUSAL_CAUSE:
2621 /* These parameters must be dissected even if !sccp_tree (so that
2622 * assoc information can be created).
2624 break;
2626 default:
2627 if (!sccp_tree) return parameter_length;
2631 parameter_tvb = tvb_new_subset_length(tvb, offset, parameter_length);
2633 switch (parameter_type) {
2635 case PARAMETER_END_OF_OPTIONAL_PARAMETERS:
2636 proto_tree_add_item(sccp_tree, hf_sccp_end_optional_param, tvb, offset, parameter_length, ENC_NA);
2637 break;
2639 case PARAMETER_DESTINATION_LOCAL_REFERENCE:
2640 dissect_sccp_dlr_param(parameter_tvb, pinfo, sccp_tree, parameter_length, sccp_info);
2641 break;
2643 case PARAMETER_SOURCE_LOCAL_REFERENCE:
2644 dissect_sccp_slr_param(parameter_tvb, pinfo, sccp_tree, parameter_length, sccp_info);
2645 break;
2647 case PARAMETER_CALLED_PARTY_ADDRESS:
2648 dissect_sccp_called_param(parameter_tvb, pinfo, sccp_tree, parameter_length, sccp_info);
2649 break;
2651 case PARAMETER_CALLING_PARTY_ADDRESS:
2652 dissect_sccp_calling_param(parameter_tvb, pinfo, sccp_tree, parameter_length, sccp_info);
2653 break;
2655 case PARAMETER_CLASS:
2656 dissect_sccp_class_param(parameter_tvb, pinfo, sccp_tree, parameter_length, sccp_info);
2657 break;
2659 case PARAMETER_SEGMENTING_REASSEMBLING:
2660 dissect_sccp_segmenting_reassembling_param(parameter_tvb, pinfo, sccp_tree,
2661 parameter_length);
2662 break;
2664 case PARAMETER_RECEIVE_SEQUENCE_NUMBER:
2665 dissect_sccp_receive_sequence_number_param(parameter_tvb, pinfo, sccp_tree,
2666 parameter_length);
2667 break;
2669 case PARAMETER_SEQUENCING_SEGMENTING:
2670 dissect_sccp_sequencing_segmenting_param(parameter_tvb, sccp_tree,
2671 parameter_length);
2672 break;
2674 case PARAMETER_CREDIT:
2675 dissect_sccp_credit_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
2676 break;
2678 case PARAMETER_RELEASE_CAUSE:
2679 dissect_sccp_release_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
2680 break;
2682 case PARAMETER_RETURN_CAUSE:
2683 dissect_sccp_return_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
2684 break;
2686 case PARAMETER_RESET_CAUSE:
2687 dissect_sccp_reset_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
2688 break;
2690 case PARAMETER_ERROR_CAUSE:
2691 dissect_sccp_error_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
2692 break;
2694 case PARAMETER_REFUSAL_CAUSE:
2695 dissect_sccp_refusal_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
2696 break;
2698 case PARAMETER_DATA:
2699 dissect_sccp_data_param(parameter_tvb, pinfo, tree, sccp_info->assoc);
2701 /* TODO? Re-adjust length of SCCP item since it may be sub-dissected */
2702 /* sccp_length = proto_item_get_len(sccp_item);
2703 * sccp_length -= parameter_length;
2704 * proto_item_set_len(sccp_item, sccp_length);
2706 * except that proto_item_get_len() is *NOT* guaranteed to return
2707 * a correct value - if the item has been "faked", it will be wrong
2709 break;
2711 case PARAMETER_SEGMENTATION:
2712 dissect_sccp_segmentation_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
2713 break;
2715 case PARAMETER_HOP_COUNTER:
2716 dissect_sccp_hop_counter_param(parameter_tvb, sccp_tree, parameter_length);
2717 break;
2719 case PARAMETER_IMPORTANCE:
2720 if (decode_mtp3_standard != ANSI_STANDARD)
2721 dissect_sccp_importance_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
2722 else
2723 dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
2724 parameter_length);
2725 break;
2727 case PARAMETER_LONG_DATA:
2728 dissect_sccp_data_param(parameter_tvb, pinfo, tree, sccp_info->assoc);
2729 break;
2731 case PARAMETER_ISNI:
2732 if (decode_mtp3_standard != ANSI_STANDARD)
2733 dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
2734 parameter_length);
2735 else
2736 dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
2737 break;
2739 default:
2740 dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
2741 parameter_length);
2742 break;
2745 return parameter_length;
2748 /* FUNCTION dissect_sccp_variable_parameter():
2749 * Dissect a variable parameter given its type and offset into tvb. Length
2750 * of the parameter is gotten from tvb[0].
2751 * Length returned is sum of (length + parameter).
2753 static uint16_t
2754 dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo,
2755 proto_tree *sccp_tree, proto_tree *tree,
2756 uint8_t parameter_type, int offset, sccp_decode_context_t* sccp_info)
2758 int remaining_length;
2759 uint16_t parameter_length;
2760 uint8_t length_length;
2761 proto_item *pi;
2763 if (parameter_type != PARAMETER_LONG_DATA) {
2764 parameter_length = tvb_get_uint8(tvb, offset);
2765 length_length = PARAMETER_LENGTH_LENGTH;
2766 } else {
2767 /* Long data parameter has 16 bit length */
2768 parameter_length = tvb_get_letohs(tvb, offset);
2769 length_length = PARAMETER_LONG_DATA_LENGTH_LENGTH;
2772 pi = proto_tree_add_uint_format(sccp_tree, hf_sccp_param_length, tvb, offset,
2773 length_length, parameter_length, "%s length: %d",
2774 val_to_str(parameter_type, sccp_parameter_values,
2775 "Unknown: %d"),
2776 parameter_length);
2777 remaining_length = tvb_reported_length_remaining(tvb, offset + length_length);
2778 if (parameter_type == PARAMETER_DATA && remaining_length > 255 && parameter_length == 255) {
2779 expert_add_info_format(pinfo, pi, &ei_sccp_externally_reassembled, "Possibly externally reassembled (remaining length %u > %u), check SCCP preferences", remaining_length, parameter_length);
2780 if (dt1_ignore_length) {
2781 parameter_length = remaining_length;
2783 } else if (!sccp_show_length) {
2784 /* The user doesn't want to see it... */
2785 /* Show the length anyway, though, if there was an error. */
2786 proto_item_set_hidden(pi);
2789 offset += length_length;
2791 dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
2792 parameter_length, sccp_info);
2794 return parameter_length + length_length;
2797 /* FUNCTION dissect_sccp_optional_parameters():
2798 * Dissect all the optional parameters given the start of the optional
2799 * parameters into tvb. Parameter types and lengths are read from tvb.
2801 static void
2802 dissect_sccp_optional_parameters(tvbuff_t *tvb, packet_info *pinfo,
2803 proto_tree *sccp_tree, proto_tree *tree,
2804 int offset, sccp_decode_context_t* sccp_info)
2806 uint8_t parameter_type;
2808 while ((parameter_type = tvb_get_uint8(tvb, offset)) !=
2809 PARAMETER_END_OF_OPTIONAL_PARAMETERS) {
2811 offset += PARAMETER_TYPE_LENGTH;
2812 offset += dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2813 parameter_type, offset, sccp_info);
2816 /* Process end of optional parameters */
2817 dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
2818 END_OF_OPTIONAL_PARAMETERS_LENGTH, sccp_info);
2822 static sccp_msg_info_t *
2823 new_ud_msg(packet_info *pinfo, uint32_t msg_type _U_)
2825 sccp_msg_info_t *m = wmem_new0(pinfo->pool, sccp_msg_info_t);
2826 m->framenum = pinfo->num;
2827 m->data.ud.calling_gt = NULL;
2828 m->data.ud.called_gt = NULL;
2830 return m;
2833 static void build_assoc_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
2834 sccp_decode_context_t *sccp_info, unsigned msg_offset)
2836 if (trace_sccp && sccp_info->assoc && (sccp_info->assoc != &no_assoc)) {
2837 proto_item *pi = proto_tree_add_uint(sccp_tree, hf_sccp_assoc_id, tvb, 0, 0, sccp_info->assoc->id);
2838 proto_item_set_generated(pi);
2839 proto_tree *pt = proto_item_add_subtree(pi, ett_sccp_assoc);
2840 if(sccp_info->assoc->imsi){
2841 proto_item *pi2 = proto_tree_add_string(sccp_tree, hf_assoc_imsi, tvb, 0, 0, sccp_info->assoc->imsi);
2842 proto_item_set_generated(pi2);
2844 if (sccp_info->assoc->msgs) {
2845 sccp_msg_info_t *m;
2846 for(m = sccp_info->assoc->msgs; m ; m = m->data.co.next) {
2847 pi = proto_tree_add_uint(pt, hf_sccp_assoc_msg, tvb, 0, 0, m->framenum);
2849 if (sccp_info->assoc->payload != SCCP_PLOAD_NONE)
2850 proto_item_append_text(pi," %s", val_to_str(sccp_info->assoc->payload, assoc_protos, "Unknown: %d"));
2852 if (m->data.co.label)
2853 proto_item_append_text(pi," %s", m->data.co.label);
2854 if (m->data.co.imsi)
2855 proto_item_append_text(pi, " %s", m->data.co.imsi);
2857 if ((m->framenum == pinfo->num) && (m->offset == msg_offset) ) {
2858 tap_queue_packet(sccp_tap, pinfo, m);
2859 proto_item_append_text(pi," (current)");
2861 proto_item_set_generated(pi);
2867 static int
2868 dissect_xudt_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
2869 proto_tree *tree, int offset, sccp_decode_context_t *sccp_info,
2870 uint16_t *optional_pointer_p, uint16_t *orig_opt_ptr_p)
2872 uint16_t variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
2873 uint16_t optional_pointer = 0, orig_opt_ptr = 0, optional_pointer1 = 0;
2874 uint8_t optional_param_type = 0;
2875 tvbuff_t *new_tvb = NULL;
2876 uint32_t source_local_ref = 0;
2877 unsigned msg_offset = tvb_offset_from_real_beginning(tvb);
2879 /* Macro for getting pointer to mandatory variable parameters */
2880 #define VARIABLE_POINTER(var, hf_var, ptr_size) \
2881 do { \
2882 if (ptr_size == POINTER_LENGTH) \
2883 var = tvb_get_uint8(tvb, offset); \
2884 else \
2885 var = tvb_get_letohs(tvb, offset); \
2886 proto_tree_add_uint(sccp_tree, hf_var, tvb, \
2887 offset, ptr_size, var); \
2888 var += offset; \
2889 if (ptr_size == POINTER_LENGTH_LONG) \
2890 var += 1; \
2891 offset += ptr_size; \
2892 } while (0)
2894 /* Macro for getting pointer to optional parameters */
2895 #define OPTIONAL_POINTER(ptr_size) \
2896 do { \
2897 if (ptr_size == POINTER_LENGTH) \
2898 orig_opt_ptr = optional_pointer = tvb_get_uint8(tvb, offset); \
2899 else \
2900 orig_opt_ptr = optional_pointer = tvb_get_letohs(tvb, offset); \
2901 proto_tree_add_uint(sccp_tree, hf_sccp_optional_pointer, tvb, \
2902 offset, ptr_size, optional_pointer); \
2903 optional_pointer += offset; \
2904 if (ptr_size == POINTER_LENGTH_LONG) \
2905 optional_pointer += 1; \
2906 offset += ptr_size; \
2907 } while (0)
2910 /* Optional parameters are Segmentation and Importance
2911 * NOTE 2 - Segmentation Should not be present in case of a single XUDT
2912 * message.
2915 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH);
2916 VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH);
2917 VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH);
2918 OPTIONAL_POINTER(POINTER_LENGTH);
2920 sccp_info->assoc = get_sccp_assoc(pinfo, msg_offset, sccp_info);
2921 build_assoc_tree(tvb, pinfo, sccp_tree, sccp_info, msg_offset);
2923 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2924 PARAMETER_CALLED_PARTY_ADDRESS,
2925 variable_pointer1, sccp_info);
2926 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2927 PARAMETER_CALLING_PARTY_ADDRESS,
2928 variable_pointer2, sccp_info);
2931 optional_pointer1 = optional_pointer;
2932 while((optional_param_type = tvb_get_uint8(tvb, optional_pointer1)) != PARAMETER_END_OF_OPTIONAL_PARAMETERS) {
2933 if (optional_param_type == PARAMETER_SEGMENTATION)
2934 break;
2935 optional_pointer1 += PARAMETER_TYPE_LENGTH;
2936 optional_pointer1 += tvb_get_uint8(tvb, optional_pointer1) + PARAMETER_LENGTH_LENGTH;
2939 if (tvb_get_uint8(tvb, optional_pointer1) == PARAMETER_SEGMENTATION) {
2940 if (!sccp_reassemble) {
2941 proto_tree_add_item(sccp_tree, hf_sccp_segmented_data, tvb, variable_pointer3, tvb_get_uint8(tvb, variable_pointer3)+1, ENC_NA);
2942 } else {
2943 uint8_t octet;
2944 bool more_frag = true;
2946 /* Get the first octet of parameter Segmentation, Ch 3.17 in Q.713
2947 * Bit 8 of octet 1 is used for First segment indication
2948 * Bit 7 of octet 1 is used to keep in the message in sequence
2949 * delivery option required by the SCCP user
2950 * Bits 6 and 5 in octet 1 are spare bits.
2951 * Bits 4-1 of octet 1 are used to indicate the number of
2952 * remaining segments.
2953 * The values 0000 to 1111 are possible; the value 0000 indicates
2954 * the last segment.
2956 octet = tvb_get_uint8(tvb, optional_pointer1+2);
2957 source_local_ref = tvb_get_letoh24(tvb, optional_pointer1+3);
2959 if ((octet & 0x0f) == 0)
2960 more_frag = false;
2962 new_tvb = sccp_reassemble_fragments(tvb, pinfo, tree, variable_pointer3, source_local_ref, more_frag);
2964 if (new_tvb)
2965 dissect_sccp_data_param(new_tvb, pinfo, tree, sccp_info->assoc);
2967 } else {
2968 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
2969 PARAMETER_DATA, variable_pointer3, sccp_info);
2972 *optional_pointer_p = optional_pointer;
2973 *orig_opt_ptr_p = orig_opt_ptr;
2974 return offset;
2977 static int
2978 dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
2979 proto_tree *tree)
2981 uint16_t variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
2982 uint16_t optional_pointer = 0, orig_opt_ptr = 0;
2983 int offset = 0;
2984 tvbuff_t *new_tvb = NULL;
2985 uint32_t source_local_ref = 0;
2986 uint8_t more;
2987 unsigned msg_offset = tvb_offset_from_real_beginning(tvb);
2988 sccp_decode_context_t sccp_info = {0, INVALID_LR, INVALID_LR, NULL, NULL};
2990 /* Extract the message type; all other processing is based on this */
2991 sccp_info.message_type = tvb_get_uint8(tvb, SCCP_MSG_TYPE_OFFSET);
2992 offset = SCCP_MSG_TYPE_LENGTH;
2994 /* Do not change col_add_fstr() to col_append_fstr() here: we _want_
2995 * this call to overwrite whatever's currently in the INFO column (e.g.,
2996 * "DATA" from the SCTP dissector).
2998 * If there's something there that should not be overwritten, whoever
2999 * put that info there should call col_set_fence() to protect it.
3001 col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
3002 val_to_str(sccp_info.message_type, sccp_message_type_acro_values, "Unknown: %d"));
3004 if (sccp_tree) {
3005 /* add the message type to the protocol tree */
3006 proto_tree_add_uint(sccp_tree, hf_sccp_message_type, tvb,
3007 SCCP_MSG_TYPE_OFFSET, SCCP_MSG_TYPE_LENGTH, sccp_info.message_type);
3011 no_assoc.calling_dpc = 0;
3012 no_assoc.called_dpc = 0;
3013 no_assoc.calling_ssn = INVALID_SSN;
3014 no_assoc.called_ssn = INVALID_SSN;
3015 no_assoc.has_fw_key = false;
3016 no_assoc.has_bw_key = false;
3017 no_assoc.payload = SCCP_PLOAD_NONE;
3018 no_assoc.called_party = NULL;
3019 no_assoc.calling_party = NULL;
3020 no_assoc.extra_info = NULL;
3022 switch (sccp_info.message_type) {
3023 case SCCP_MSG_TYPE_CR:
3024 /* TTC and NTT (Japan) say that the connection-oriented messages are
3025 * deleted (not standardized), but they appear to be used anyway, so
3026 * we'll dissect it...
3028 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3029 PARAMETER_SOURCE_LOCAL_REFERENCE,
3030 offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info);
3031 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3032 PARAMETER_CLASS, offset,
3033 PROTOCOL_CLASS_LENGTH, &sccp_info);
3034 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3035 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3037 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH);
3038 OPTIONAL_POINTER(POINTER_LENGTH);
3040 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3041 PARAMETER_CALLED_PARTY_ADDRESS,
3042 variable_pointer1, &sccp_info);
3043 break;
3045 case SCCP_MSG_TYPE_CC:
3046 /* TODO: connection has been established; theoretically we could keep
3047 * keep track of the SLR/DLR with the called/calling from the CR and
3048 * track the connection (e.g., on subsequent messages regarding this
3049 * SLR we could set the global vars "call*_ssn" so data could get
3050 * sub-dissected).
3052 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3053 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3054 offset,
3055 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3056 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3057 PARAMETER_SOURCE_LOCAL_REFERENCE,
3058 offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info);
3060 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3061 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3063 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3064 PARAMETER_CLASS, offset,
3065 PROTOCOL_CLASS_LENGTH, &sccp_info);
3066 OPTIONAL_POINTER(POINTER_LENGTH);
3067 break;
3069 case SCCP_MSG_TYPE_CREF:
3070 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3071 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3072 offset,
3073 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3075 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3076 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3078 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3079 PARAMETER_REFUSAL_CAUSE, offset,
3080 REFUSAL_CAUSE_LENGTH, &sccp_info);
3081 OPTIONAL_POINTER(POINTER_LENGTH);
3082 break;
3084 case SCCP_MSG_TYPE_RLSD:
3085 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3086 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3087 offset,
3088 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3089 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3090 PARAMETER_SOURCE_LOCAL_REFERENCE,
3091 offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info);
3093 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3094 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3096 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3097 PARAMETER_RELEASE_CAUSE, offset,
3098 RELEASE_CAUSE_LENGTH, &sccp_info);
3100 OPTIONAL_POINTER(POINTER_LENGTH);
3101 break;
3103 case SCCP_MSG_TYPE_RLC:
3104 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3105 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3106 offset,
3107 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3108 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3109 PARAMETER_SOURCE_LOCAL_REFERENCE,
3110 offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info);
3112 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3113 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3114 break;
3116 case SCCP_MSG_TYPE_DT1:
3118 int remaining_length;
3119 source_local_ref = tvb_get_letoh24(tvb, offset);
3120 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3121 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3122 offset,
3123 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3125 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3126 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3128 more = tvb_get_uint8(tvb, offset) & SEGMENTING_REASSEMBLING_MASK;
3130 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3131 PARAMETER_SEGMENTING_REASSEMBLING,
3132 offset, SEGMENTING_REASSEMBLING_LENGTH, &sccp_info);
3133 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH);
3135 /* Reassemble */
3136 if (!sccp_reassemble) {
3137 proto_tree_add_item(sccp_tree, hf_sccp_segmented_data, tvb, variable_pointer1,
3138 tvb_get_uint8(tvb, variable_pointer1)+1, ENC_NA);
3139 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3140 PARAMETER_DATA, variable_pointer1, &sccp_info);
3142 } else {
3143 remaining_length = tvb_reported_length_remaining(tvb, variable_pointer1 + 1);
3144 if(dt1_ignore_length && remaining_length > 255) {
3145 new_tvb = tvb_new_subset_length(tvb, variable_pointer1 + 1, remaining_length);
3146 } else {
3147 new_tvb = sccp_reassemble_fragments(tvb, pinfo, tree, variable_pointer1, source_local_ref, more);
3150 if (new_tvb)
3151 dissect_sccp_data_param(new_tvb, pinfo, tree, sccp_info.assoc);
3154 /* End reassemble */
3155 break;
3158 case SCCP_MSG_TYPE_DT2:
3159 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3160 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3161 offset,
3162 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3164 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3165 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3167 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3168 PARAMETER_SEQUENCING_SEGMENTING, offset,
3169 SEQUENCING_SEGMENTING_LENGTH, &sccp_info);
3170 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH);
3172 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3173 PARAMETER_DATA, variable_pointer1, &sccp_info);
3175 break;
3177 case SCCP_MSG_TYPE_AK:
3178 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3179 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3180 offset,
3181 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3183 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3184 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3186 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3187 PARAMETER_RECEIVE_SEQUENCE_NUMBER,
3188 offset, RECEIVE_SEQUENCE_NUMBER_LENGTH, &sccp_info);
3189 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3190 PARAMETER_CREDIT, offset, CREDIT_LENGTH, &sccp_info);
3191 break;
3193 case SCCP_MSG_TYPE_UDT:
3194 sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type);
3196 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3197 PARAMETER_CLASS, offset,
3198 PROTOCOL_CLASS_LENGTH, &sccp_info);
3199 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH);
3200 VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH);
3201 VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH);
3203 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3204 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3206 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3207 PARAMETER_CALLED_PARTY_ADDRESS,
3208 variable_pointer1, &sccp_info);
3209 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3210 PARAMETER_CALLING_PARTY_ADDRESS,
3211 variable_pointer2, &sccp_info);
3213 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
3214 variable_pointer3, &sccp_info);
3215 break;
3217 case SCCP_MSG_TYPE_UDTS:
3219 bool save_in_error_pkt = pinfo->flags.in_error_pkt;
3220 pinfo->flags.in_error_pkt = true;
3222 sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type);
3224 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3225 PARAMETER_RETURN_CAUSE, offset,
3226 RETURN_CAUSE_LENGTH, &sccp_info);
3228 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH);
3229 VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH);
3230 VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH);
3232 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3233 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3235 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3236 PARAMETER_CALLED_PARTY_ADDRESS,
3237 variable_pointer1, &sccp_info);
3239 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3240 PARAMETER_CALLING_PARTY_ADDRESS,
3241 variable_pointer2, &sccp_info);
3243 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
3244 variable_pointer3, &sccp_info);
3245 pinfo->flags.in_error_pkt = save_in_error_pkt;
3246 break;
3249 case SCCP_MSG_TYPE_ED:
3250 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3251 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3252 offset,
3253 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3255 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3256 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3258 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH);
3260 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
3261 variable_pointer1, &sccp_info);
3262 break;
3264 case SCCP_MSG_TYPE_EA:
3265 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3266 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3267 offset,
3268 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3269 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3270 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3271 break;
3273 case SCCP_MSG_TYPE_RSR:
3274 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3275 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3276 offset,
3277 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3278 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3279 PARAMETER_SOURCE_LOCAL_REFERENCE,
3280 offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info);
3281 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3282 PARAMETER_RESET_CAUSE, offset,
3283 RESET_CAUSE_LENGTH, &sccp_info);
3284 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3285 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3286 break;
3288 case SCCP_MSG_TYPE_RSC:
3289 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3290 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3291 offset,
3292 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3293 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3294 PARAMETER_SOURCE_LOCAL_REFERENCE,
3295 offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info);
3296 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3297 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3298 break;
3300 case SCCP_MSG_TYPE_ERR:
3301 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3302 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3303 offset,
3304 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3305 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3306 PARAMETER_ERROR_CAUSE, offset,
3307 ERROR_CAUSE_LENGTH, &sccp_info);
3308 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3309 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3310 break;
3312 case SCCP_MSG_TYPE_IT:
3313 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3314 PARAMETER_DESTINATION_LOCAL_REFERENCE,
3315 offset,
3316 DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info);
3317 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3318 PARAMETER_SOURCE_LOCAL_REFERENCE,
3319 offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info);
3320 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3321 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3322 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3323 PARAMETER_CLASS, offset,
3324 PROTOCOL_CLASS_LENGTH, &sccp_info);
3325 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3326 PARAMETER_SEQUENCING_SEGMENTING,
3327 offset, SEQUENCING_SEGMENTING_LENGTH, &sccp_info);
3328 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3329 PARAMETER_CREDIT, offset, CREDIT_LENGTH, &sccp_info);
3330 break;
3332 case SCCP_MSG_TYPE_XUDT:
3333 sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type);
3334 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3335 PARAMETER_CLASS, offset,
3336 PROTOCOL_CLASS_LENGTH, &sccp_info);
3337 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3338 PARAMETER_HOP_COUNTER, offset,
3339 HOP_COUNTER_LENGTH, &sccp_info);
3341 offset = dissect_xudt_common(tvb, pinfo, sccp_tree, tree, offset, &sccp_info,
3342 &optional_pointer, &orig_opt_ptr);
3343 break;
3345 case SCCP_MSG_TYPE_XUDTS:
3347 bool save_in_error_pkt = pinfo->flags.in_error_pkt;
3348 pinfo->flags.in_error_pkt = true;
3350 sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type);
3351 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3352 PARAMETER_RETURN_CAUSE, offset,
3353 RETURN_CAUSE_LENGTH, &sccp_info);
3354 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3355 PARAMETER_HOP_COUNTER, offset,
3356 HOP_COUNTER_LENGTH, &sccp_info);
3358 offset = dissect_xudt_common(tvb, pinfo, sccp_tree, tree, offset, &sccp_info,
3359 &optional_pointer, &orig_opt_ptr);
3361 pinfo->flags.in_error_pkt = save_in_error_pkt;
3362 break;
3364 case SCCP_MSG_TYPE_LUDT:
3365 sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type);
3367 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3368 PARAMETER_CLASS, offset,
3369 PROTOCOL_CLASS_LENGTH, &sccp_info);
3370 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3371 PARAMETER_HOP_COUNTER, offset,
3372 HOP_COUNTER_LENGTH, &sccp_info);
3374 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG);
3375 VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG);
3376 VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG);
3377 OPTIONAL_POINTER(POINTER_LENGTH_LONG);
3379 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3380 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3382 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3383 PARAMETER_CALLED_PARTY_ADDRESS,
3384 variable_pointer1, &sccp_info);
3385 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3386 PARAMETER_CALLING_PARTY_ADDRESS,
3387 variable_pointer2, &sccp_info);
3388 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3389 PARAMETER_LONG_DATA, variable_pointer3, &sccp_info);
3390 break;
3392 case SCCP_MSG_TYPE_LUDTS:
3393 sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type);
3394 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3395 PARAMETER_RETURN_CAUSE, offset,
3396 RETURN_CAUSE_LENGTH, &sccp_info);
3397 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
3398 PARAMETER_HOP_COUNTER, offset,
3399 HOP_COUNTER_LENGTH, &sccp_info);
3401 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG);
3402 VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG);
3403 VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG);
3404 OPTIONAL_POINTER(POINTER_LENGTH_LONG);
3406 sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info);
3407 build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset);
3409 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3410 PARAMETER_CALLED_PARTY_ADDRESS,
3411 variable_pointer1, &sccp_info);
3412 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3413 PARAMETER_CALLING_PARTY_ADDRESS,
3414 variable_pointer2, &sccp_info);
3415 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
3416 PARAMETER_LONG_DATA, variable_pointer3, &sccp_info);
3417 break;
3419 default:
3420 dissect_sccp_unknown_message(tvb, sccp_tree);
3423 if (orig_opt_ptr)
3424 dissect_sccp_optional_parameters(tvb, pinfo, sccp_tree, tree,
3425 optional_pointer, &sccp_info);
3427 return offset;
3430 static int
3431 dissect_sccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3433 proto_item *sccp_item = NULL;
3434 proto_tree *sccp_tree = NULL;
3435 const mtp3_addr_pc_t *mtp3_addr_p;
3437 if ((pinfo->src.type == ss7pc_address_type) &&
3438 ((mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data)->type <= CHINESE_ITU_STANDARD)) {
3440 * Allow a protocol beneath to specify how the SCCP layer should be
3441 * dissected.
3443 * It is possible to have multiple sets of SCCP traffic some of which is
3444 * ITU and some of which is ANSI.
3445 * An example is A-interface traffic having ANSI MTP3/ANSI SCCP/3GPP2 IOS
3446 * and at the same time ITU MTP3/ITU SCCP/ANSI TCAP/ANSI MAP.
3448 decode_mtp3_standard = mtp3_addr_p->type;
3449 } else {
3450 decode_mtp3_standard = (Standard_Type)mtp3_standard;
3453 /* Make entry in the Protocol column on summary display */
3454 switch (decode_mtp3_standard) {
3455 case ITU_STANDARD:
3456 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Int. ITU)");
3457 break;
3458 case ANSI_STANDARD:
3459 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (ANSI)");
3460 break;
3461 case CHINESE_ITU_STANDARD:
3462 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Chin. ITU)");
3463 break;
3464 case JAPAN_STANDARD:
3465 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Japan)");
3466 break;
3469 /* In the interest of speed, if "tree" is NULL, don't do any work not
3470 necessary to generate protocol tree items. */
3471 if (tree) {
3472 /* create the sccp protocol tree */
3473 sccp_item = proto_tree_add_item(tree, proto_sccp, tvb, 0, -1, ENC_NA);
3474 sccp_tree = proto_item_add_subtree(sccp_item, ett_sccp);
3477 /* Set whether message is UPLINK, DOWNLINK, or of UNKNOWN direction */
3479 if (pinfo->src.type == ss7pc_address_type) {
3481 * XXX - we assume that the "data" pointers of the source and destination
3482 * addresses are set to point to "mtp3_addr_pc_t" structures, so that
3483 * we can safely cast them.
3485 mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data;
3487 if (sccp_source_pc_global == mtp3_addr_p->pc) {
3488 pinfo->p2p_dir = P2P_DIR_SENT;
3489 } else {
3490 /* assuming if src was SS7 PC then dst will be too */
3491 mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->dst.data;
3493 if (sccp_source_pc_global == mtp3_addr_p->pc)
3495 pinfo->p2p_dir = P2P_DIR_RECV;
3496 } else {
3497 pinfo->p2p_dir = P2P_DIR_UNKNOWN;
3502 /* dissect the message */
3503 dissect_sccp_message(tvb, pinfo, sccp_tree, tree);
3504 return tvb_captured_length(tvb);
3507 /*** SccpUsers Table **/
3509 static struct _sccp_ul {
3510 unsigned id;
3511 bool uses_tcap;
3512 dissector_handle_t *handlep;
3513 } user_list[] = {
3515 {SCCP_USER_DATA, false, &data_handle},
3516 {SCCP_USER_TCAP, false, &tcap_handle},
3517 {SCCP_USER_RANAP, false, &ranap_handle},
3518 {SCCP_USER_BSSAP, false, &bssap_handle},
3519 {SCCP_USER_GSMMAP, true, &gsmmap_handle},
3520 {SCCP_USER_CAMEL, true, &camel_handle},
3521 {SCCP_USER_INAP, true, &inap_handle},
3522 {SCCP_USER_BSAP, false, &bsap_handle},
3523 {SCCP_USER_BSSAP_LE, false, &bssap_le_handle},
3524 {SCCP_USER_BSSAP_PLUS, false, &bssap_plus_handle},
3525 {0, false, NULL}
3528 static bool
3529 sccp_users_update_cb(void *r, char **err)
3531 sccp_user_t *u = (sccp_user_t *)r;
3532 struct _sccp_ul *c;
3533 range_t *empty;
3535 empty = range_empty(NULL);
3536 if (ranges_are_equal(u->called_pc, empty)) {
3537 *err = g_strdup("Must specify a PC");
3538 wmem_free(NULL, empty);
3539 return false;
3542 if (ranges_are_equal(u->called_ssn, empty)) {
3543 *err = g_strdup("Must specify an SSN");
3544 wmem_free(NULL, empty);
3545 return false;
3548 wmem_free(NULL, empty);
3549 for (c=user_list; c->handlep; c++) {
3550 if (c->id == u->user) {
3551 u->uses_tcap = c->uses_tcap;
3552 u->handlep = c->handlep;
3553 return true;
3557 u->uses_tcap = false;
3558 u->handlep = &data_handle;
3559 return true;
3562 static void *
3563 sccp_users_copy_cb(void *n, const void *o, size_t siz _U_)
3565 const sccp_user_t *u = (const sccp_user_t *)o;
3566 sccp_user_t *un = (sccp_user_t *)n;
3568 un->ni = u->ni;
3569 un->user = u->user;
3570 un->uses_tcap = u->uses_tcap;
3571 un->handlep = u->handlep;
3573 if (u->called_pc)
3574 un->called_pc = range_copy(NULL, u->called_pc);
3575 if (u->called_ssn)
3576 un->called_ssn = range_copy(NULL, u->called_ssn);
3578 return n;
3581 static void
3582 sccp_users_free_cb(void *r)
3584 sccp_user_t *u = (sccp_user_t *)r;
3585 if (u->called_pc) wmem_free(NULL, u->called_pc);
3586 if (u->called_ssn) wmem_free(NULL, u->called_ssn);
3590 UAT_DEC_CB_DEF(sccp_users, ni, sccp_user_t)
3591 UAT_RANGE_CB_DEF(sccp_users, called_pc, sccp_user_t)
3592 UAT_RANGE_CB_DEF(sccp_users, called_ssn, sccp_user_t)
3593 UAT_VS_DEF(sccp_users, user, sccp_user_t, unsigned, SCCP_USER_DATA, "Data")
3595 /** End SccpUsersTable **/
3598 static void
3599 init_sccp(void)
3601 next_assoc_id = 1;
3602 sccp_reassembly_id_next = 1;
3605 /* Register the protocol with Wireshark */
3606 void
3607 proto_register_sccp(void)
3609 /* Setup list of header fields */
3610 static hf_register_info hf[] = {
3611 { &hf_sccp_message_type,
3612 { "Message Type", "sccp.message_type",
3613 FT_UINT8, BASE_HEX, VALS(sccp_message_type_values), 0x0,
3614 NULL, HFILL}
3616 { &hf_sccp_variable_pointer1,
3617 { "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1",
3618 FT_UINT16, BASE_DEC, NULL, 0x0,
3619 NULL, HFILL}
3621 { &hf_sccp_variable_pointer2,
3622 { "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2",
3623 FT_UINT16, BASE_DEC, NULL, 0x0,
3624 NULL, HFILL}
3626 { &hf_sccp_variable_pointer3,
3627 { "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3",
3628 FT_UINT16, BASE_DEC, NULL, 0x0,
3629 NULL, HFILL}
3631 { &hf_sccp_optional_pointer,
3632 { "Pointer to Optional parameter", "sccp.optional_pointer",
3633 FT_UINT16, BASE_DEC, NULL, 0x0,
3634 NULL, HFILL}
3636 { &hf_sccp_param_length,
3637 { "Variable parameter length", "sccp.parameter_length",
3638 FT_UINT16, BASE_DEC, NULL, 0x0,
3639 NULL, HFILL}
3641 { &hf_sccp_ssn,
3642 { "Called or Calling SubSystem Number", "sccp.ssn",
3643 FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
3644 NULL, HFILL}
3646 { &hf_sccp_gt_digits,
3647 { "Called or Calling GT Digits", "sccp.digits",
3648 FT_STRING, BASE_NONE, NULL, 0x0,
3649 NULL, HFILL }
3651 { &hf_sccp_called_ansi_national_indicator,
3652 { "National Indicator", "sccp.called.ni",
3653 FT_UINT8, BASE_HEX, VALS(sccp_ansi_national_indicator_values), ANSI_NATIONAL_MASK,
3654 NULL, HFILL}
3656 { &hf_sccp_called_itu_natl_use_bit,
3657 { "Reserved for national use", "sccp.called.reserved",
3658 FT_UINT8, BASE_HEX, NULL, ITU_RESERVED_MASK,
3659 NULL, HFILL}
3661 { &hf_sccp_called_routing_indicator,
3662 { "Routing Indicator", "sccp.called.ri",
3663 FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
3664 NULL, HFILL}
3666 { &hf_sccp_called_itu_global_title_indicator,
3667 { "Global Title Indicator", "sccp.called.gti",
3668 FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
3669 NULL, HFILL}
3671 { &hf_sccp_called_ansi_global_title_indicator,
3672 { "Global Title Indicator", "sccp.called.gti",
3673 FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
3674 NULL, HFILL}
3676 { &hf_sccp_called_itu_ssn_indicator,
3677 { "SubSystem Number Indicator", "sccp.called.ssni",
3678 FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
3679 NULL, HFILL}
3681 { &hf_sccp_called_itu_point_code_indicator,
3682 { "Point Code Indicator", "sccp.called.pci",
3683 FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
3684 NULL, HFILL}
3686 { &hf_sccp_called_ansi_ssn_indicator,
3687 { "SubSystem Number Indicator", "sccp.called.ssni",
3688 FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
3689 NULL, HFILL}
3691 { &hf_sccp_called_ansi_point_code_indicator,
3692 { "Point Code Indicator", "sccp.called.pci",
3693 FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
3694 NULL, HFILL}
3696 { &hf_sccp_called_ssn,
3697 { "SubSystem Number", "sccp.called.ssn",
3698 FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
3699 NULL, HFILL}
3701 { &hf_sccp_called_itu_pc,
3702 { "PC", "sccp.called.pc",
3703 FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
3704 NULL, HFILL}
3706 { &hf_sccp_called_ansi_pc,
3707 { "PC", "sccp.called.ansi_pc",
3708 FT_STRING, BASE_NONE, NULL, 0x0,
3709 NULL, HFILL}
3711 { &hf_sccp_called_chinese_pc,
3712 { "PC", "sccp.called.chinese_pc",
3713 FT_STRING, BASE_NONE, NULL, 0x0,
3714 NULL, HFILL}
3716 { &hf_sccp_called_japan_pc,
3717 { "PC", "sccp.called.pc",
3718 FT_UINT16, BASE_DEC, NULL, 0x0,
3719 NULL, HFILL}
3721 { &hf_sccp_called_pc_network,
3722 { "PC Network", "sccp.called.network",
3723 FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
3724 NULL, HFILL }
3726 { &hf_sccp_called_pc_cluster,
3727 { "PC Cluster", "sccp.called.cluster",
3728 FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
3729 NULL, HFILL }
3731 { &hf_sccp_called_pc_member,
3732 { "PC Member", "sccp.called.member",
3733 FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
3734 NULL, HFILL }
3736 { &hf_sccp_called_gt_nai,
3737 { "Nature of Address Indicator", "sccp.called.nai",
3738 FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
3739 NULL, HFILL }
3741 { &hf_sccp_called_gt_oe,
3742 { "Odd/Even Indicator", "sccp.called.oe",
3743 FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
3744 NULL, HFILL }
3746 { &hf_sccp_called_gt_tt,
3747 { "Translation Type", "sccp.called.tt",
3748 FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
3749 NULL, HFILL }
3751 { &hf_sccp_called_gt_np,
3752 { "Numbering Plan", "sccp.called.np",
3753 FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
3754 NULL, HFILL }
3756 { &hf_sccp_called_gt_es,
3757 { "Encoding Scheme", "sccp.called.es",
3758 FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
3759 NULL, HFILL }
3761 { &hf_sccp_called_gt_digits,
3762 { "Called Party Digits", "sccp.called.digits",
3763 FT_STRING, BASE_NONE, NULL, 0x0,
3764 NULL, HFILL }
3766 { &hf_sccp_called_gt_digits_length,
3767 { "Number of Called Party Digits", "sccp.called.digits.length",
3768 FT_UINT8, BASE_DEC, NULL, 0x0,
3769 NULL, HFILL }
3771 { &hf_sccp_calling_ansi_national_indicator,
3772 { "National Indicator", "sccp.calling.ni",
3773 FT_UINT8, BASE_HEX, VALS(sccp_ansi_national_indicator_values), ANSI_NATIONAL_MASK,
3774 NULL, HFILL}
3776 { &hf_sccp_calling_itu_natl_use_bit,
3777 { "Reserved for national use", "sccp.calling.reserved",
3778 FT_UINT8, BASE_HEX, NULL, ITU_RESERVED_MASK,
3779 NULL, HFILL}
3781 { &hf_sccp_calling_routing_indicator,
3782 { "Routing Indicator", "sccp.calling.ri",
3783 FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
3784 NULL, HFILL}
3786 { &hf_sccp_calling_itu_global_title_indicator,
3787 { "Global Title Indicator", "sccp.calling.gti",
3788 FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
3789 NULL, HFILL}
3791 { &hf_sccp_calling_ansi_global_title_indicator,
3792 { "Global Title Indicator", "sccp.calling.gti",
3793 FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
3794 NULL, HFILL}
3796 { &hf_sccp_calling_itu_ssn_indicator,
3797 { "SubSystem Number Indicator", "sccp.calling.ssni",
3798 FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
3799 NULL, HFILL}
3801 { &hf_sccp_calling_itu_point_code_indicator,
3802 { "Point Code Indicator", "sccp.calling.pci",
3803 FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
3804 NULL, HFILL}
3806 { &hf_sccp_calling_ansi_ssn_indicator,
3807 { "SubSystem Number Indicator", "sccp.calling.ssni",
3808 FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
3809 NULL, HFILL}
3811 { &hf_sccp_calling_ansi_point_code_indicator,
3812 { "Point Code Indicator", "sccp.calling.pci",
3813 FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
3814 NULL, HFILL}
3816 { &hf_sccp_calling_ssn,
3817 { "SubSystem Number", "sccp.calling.ssn",
3818 FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
3819 NULL, HFILL}
3821 { &hf_sccp_calling_itu_pc,
3822 { "PC", "sccp.calling.pc",
3823 FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
3824 NULL, HFILL}
3826 { &hf_sccp_calling_ansi_pc,
3827 { "PC", "sccp.calling.ansi_pc",
3828 FT_STRING, BASE_NONE, NULL, 0x0,
3829 NULL, HFILL}
3831 { &hf_sccp_calling_chinese_pc,
3832 { "PC", "sccp.calling.chinese_pc",
3833 FT_STRING, BASE_NONE, NULL, 0x0,
3834 NULL, HFILL}
3836 { &hf_sccp_calling_japan_pc,
3837 { "PC", "sccp.calling.pc",
3838 FT_UINT16, BASE_DEC, NULL, 0x0,
3839 NULL, HFILL}
3841 { &hf_sccp_calling_pc_network,
3842 { "PC Network", "sccp.calling.network",
3843 FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
3844 NULL, HFILL }
3846 { &hf_sccp_calling_pc_cluster,
3847 { "PC Cluster", "sccp.calling.cluster",
3848 FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
3849 NULL, HFILL }
3851 { &hf_sccp_calling_pc_member,
3852 { "PC Member", "sccp.calling.member",
3853 FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
3854 NULL, HFILL }
3856 { &hf_sccp_calling_gt_nai,
3857 { "Nature of Address Indicator", "sccp.calling.nai",
3858 FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
3859 NULL, HFILL }
3861 { &hf_sccp_calling_gt_oe,
3862 { "Odd/Even Indicator", "sccp.calling.oe",
3863 FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
3864 NULL, HFILL }
3866 { &hf_sccp_calling_gt_tt,
3867 { "Translation Type", "sccp.calling.tt",
3868 FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
3869 NULL, HFILL }
3871 { &hf_sccp_calling_gt_np,
3872 { "Numbering Plan", "sccp.calling.np",
3873 FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
3874 NULL, HFILL }
3876 { &hf_sccp_calling_gt_es,
3877 { "Encoding Scheme", "sccp.calling.es",
3878 FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
3879 NULL, HFILL }
3881 { &hf_sccp_calling_gt_digits,
3882 { "Calling Party Digits", "sccp.calling.digits",
3883 FT_STRING, BASE_NONE, NULL, 0x0,
3884 NULL, HFILL }
3886 { &hf_sccp_calling_gt_digits_length,
3887 { "Number of Calling Party Digits", "sccp.calling.digits.length",
3888 FT_UINT8, BASE_DEC, NULL, 0x0,
3889 NULL, HFILL }
3891 { &hf_sccp_dlr,
3892 { "Destination Local Reference", "sccp.dlr",
3893 FT_UINT24, BASE_HEX, NULL, 0x0,
3894 NULL, HFILL}
3896 { &hf_sccp_slr,
3897 { "Source Local Reference", "sccp.slr",
3898 FT_UINT24, BASE_HEX, NULL, 0x0,
3899 NULL, HFILL}
3901 { &hf_sccp_lr,
3902 { "Local Reference", "sccp.lr",
3903 FT_UINT24, BASE_HEX, NULL, 0x0,
3904 NULL, HFILL}
3906 { &hf_sccp_class,
3907 { "Class", "sccp.class",
3908 FT_UINT8, BASE_HEX, NULL, CLASS_CLASS_MASK,
3909 NULL, HFILL}
3911 { &hf_sccp_handling,
3912 { "Message handling", "sccp.handling",
3913 FT_UINT8, BASE_HEX, VALS(sccp_class_handling_values), CLASS_SPARE_HANDLING_MASK,
3914 NULL, HFILL}
3916 { &hf_sccp_more,
3917 { "More data", "sccp.more",
3918 FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEGMENTING_REASSEMBLING_MASK,
3919 NULL, HFILL}
3921 { &hf_sccp_rsn,
3922 { "Receive Sequence Number", "sccp.rsn",
3923 FT_UINT8, BASE_HEX, NULL, RSN_MASK,
3924 NULL, HFILL}
3926 { &hf_sccp_sequencing_segmenting_ssn,
3927 { "Sequencing Segmenting: Send Sequence Number", "sccp.sequencing_segmenting.ssn",
3928 FT_UINT8, BASE_HEX, NULL, SEND_SEQUENCE_NUMBER_MASK,
3929 NULL, HFILL}
3931 { &hf_sccp_sequencing_segmenting_rsn,
3932 { "Sequencing Segmenting: Receive Sequence Number", "sccp.sequencing_segmenting.rsn",
3933 FT_UINT8, BASE_HEX, NULL, RECEIVE_SEQUENCE_NUMBER_MASK,
3934 NULL, HFILL}
3936 { &hf_sccp_sequencing_segmenting_more,
3937 { "Sequencing Segmenting: More", "sccp.sequencing_segmenting.more",
3938 FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEQUENCING_SEGMENTING_MORE_MASK,
3939 NULL, HFILL}
3941 { &hf_sccp_credit,
3942 { "Credit", "sccp.credit",
3943 FT_UINT8, BASE_HEX, NULL, 0x0,
3944 NULL, HFILL}
3946 { &hf_sccp_release_cause,
3947 { "Release Cause", "sccp.release_cause",
3948 FT_UINT8, BASE_HEX, VALS(sccp_release_cause_values), 0x0,
3949 NULL, HFILL}
3951 { &hf_sccp_return_cause,
3952 { "Return Cause", "sccp.return_cause",
3953 FT_UINT8, BASE_HEX, VALS(sccp_return_cause_values), 0x0,
3954 NULL, HFILL}
3956 { &hf_sccp_reset_cause,
3957 { "Reset Cause", "sccp.reset_cause",
3958 FT_UINT8, BASE_HEX, VALS(sccp_reset_cause_values), 0x0,
3959 NULL, HFILL}
3961 { &hf_sccp_error_cause,
3962 { "Error Cause", "sccp.error_cause",
3963 FT_UINT8, BASE_HEX, VALS(sccp_error_cause_values), 0x0,
3964 NULL, HFILL}
3966 { &hf_sccp_refusal_cause,
3967 { "Refusal Cause", "sccp.refusal_cause",
3968 FT_UINT8, BASE_HEX, VALS(sccp_refusal_cause_values), 0x0,
3969 NULL, HFILL}
3971 { &hf_sccp_segmentation_first,
3972 { "Segmentation: First", "sccp.segmentation.first",
3973 FT_UINT8, BASE_HEX, VALS(sccp_segmentation_first_segment_values), SEGMENTATION_FIRST_SEGMENT_MASK,
3974 NULL, HFILL}
3976 { &hf_sccp_segmentation_class,
3977 { "Segmentation: Class", "sccp.segmentation.class",
3978 FT_UINT8, BASE_HEX, VALS(sccp_segmentation_class_values), SEGMENTATION_CLASS_MASK,
3979 NULL, HFILL}
3981 { &hf_sccp_segmentation_remaining,
3982 { "Segmentation: Remaining", "sccp.segmentation.remaining",
3983 FT_UINT8, BASE_HEX, NULL, SEGMENTATION_REMAINING_MASK,
3984 NULL, HFILL}
3986 { &hf_sccp_segmentation_slr,
3987 { "Segmentation: Source Local Reference", "sccp.segmentation.slr",
3988 FT_UINT24, BASE_HEX, NULL, 0x0,
3989 NULL, HFILL}
3991 { &hf_sccp_hop_counter,
3992 { "Hop Counter", "sccp.hops",
3993 FT_UINT8, BASE_HEX, NULL, 0x0,
3994 NULL, HFILL}
3996 { &hf_sccp_importance,
3997 { "Importance", "sccp.importance",
3998 FT_UINT8, BASE_HEX, NULL, IMPORTANCE_IMPORTANCE_MASK,
3999 NULL, HFILL}
4001 /* ISNI is ANSI only */
4002 { &hf_sccp_ansi_isni_mi,
4003 { "ISNI Mark for Identification Indicator", "sccp.isni.mi",
4004 FT_UINT8, BASE_HEX, VALS(sccp_isni_mark_for_id_values), ANSI_ISNI_MI_MASK,
4005 NULL, HFILL}
4007 { &hf_sccp_ansi_isni_iri,
4008 { "ISNI Routing Indicator", "sccp.isni.iri",
4009 FT_UINT8, BASE_HEX, VALS(sccp_isni_iri_values), ANSI_ISNI_IRI_MASK,
4010 NULL, HFILL}
4012 { &hf_sccp_ansi_isni_ti,
4013 { "ISNI Type Indicator", "sccp.isni.ti",
4014 FT_UINT8, BASE_HEX, VALS(sccp_isni_ti_values), ANSI_ISNI_TI_MASK,
4015 NULL, HFILL}
4017 { &hf_sccp_ansi_isni_netspec,
4018 { "ISNI Network Specific (Type 1)", "sccp.isni.netspec",
4019 FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_NETSPEC_MASK,
4020 NULL, HFILL}
4022 { &hf_sccp_ansi_isni_counter,
4023 { "ISNI Counter", "sccp.isni.counter",
4024 FT_UINT8, BASE_DEC, NULL, ANSI_ISNI_COUNTER_MASK,
4025 NULL, HFILL}
4027 { &hf_sccp_ansi_isni_network,
4028 { "Network ID network", "sccp.isni.network",
4029 FT_UINT8, BASE_DEC, NULL, 0x0,
4030 NULL, HFILL}
4032 { &hf_sccp_ansi_isni_cluster,
4033 { "Network ID cluster", "sccp.isni.cluster",
4034 FT_UINT8, BASE_DEC, NULL, 0x0,
4035 NULL, HFILL}
4037 {&hf_sccp_xudt_msg_fragments,
4038 { "Message fragments", "sccp.msg.fragments",
4039 FT_NONE, BASE_NONE, NULL, 0x00,
4040 NULL, HFILL }
4042 {&hf_sccp_xudt_msg_fragment,
4043 { "Message fragment", "sccp.msg.fragment",
4044 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
4045 NULL, HFILL }
4047 {&hf_sccp_xudt_msg_fragment_overlap,
4048 { "Message fragment overlap", "sccp.msg.fragment.overlap",
4049 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4050 NULL, HFILL }
4052 {&hf_sccp_xudt_msg_fragment_overlap_conflicts,
4053 { "Message fragment overlapping with conflicting data", "sccp.msg.fragment.overlap.conflicts",
4054 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4055 NULL, HFILL }
4057 {&hf_sccp_xudt_msg_fragment_multiple_tails,
4058 { "Message has multiple tail fragments", "sccp.msg.fragment.multiple_tails",
4059 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4060 NULL, HFILL }
4062 {&hf_sccp_xudt_msg_fragment_too_long_fragment,
4063 { "Message fragment too long", "sccp.msg.fragment.too_long_fragment",
4064 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4065 NULL, HFILL }
4067 {&hf_sccp_xudt_msg_fragment_error,
4068 { "Message defragmentation error", "sccp.msg.fragment.error",
4069 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
4070 NULL, HFILL }
4072 {&hf_sccp_xudt_msg_fragment_count,
4073 { "Message fragment count", "sccp.msg.fragment.count",
4074 FT_UINT32, BASE_DEC, NULL, 0x00,
4075 NULL, HFILL }
4077 {&hf_sccp_xudt_msg_reassembled_in,
4078 { "Reassembled in", "sccp.msg.reassembled.in",
4079 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
4080 NULL, HFILL }
4082 {&hf_sccp_xudt_msg_reassembled_length,
4083 { "Reassembled SCCP length", "sccp.msg.reassembled.length",
4084 FT_UINT32, BASE_DEC, NULL, 0x00,
4085 NULL, HFILL }
4087 { &hf_sccp_assoc_id,
4088 { "Association ID", "sccp.assoc.id",
4089 FT_UINT32, BASE_DEC, NULL, 0x0,
4090 NULL, HFILL}
4092 {&hf_sccp_assoc_msg,
4093 { "Message in frame", "sccp.assoc.msg",
4094 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
4095 NULL, HFILL }
4097 {&hf_sccp_segmented_data,
4098 { "Segmented Data", "sccp.segmented_data",
4099 FT_BYTES, BASE_NONE, NULL, 0x00,
4100 NULL, HFILL }
4102 {&hf_sccp_linked_dissector,
4103 { "Linked dissector", "sccp.linked_dissector",
4104 FT_STRING, BASE_NONE, NULL, 0x00,
4105 NULL, HFILL }
4107 {&hf_sccp_end_optional_param,
4108 { "End of Optional", "sccp.end_optional_param",
4109 FT_NONE, BASE_NONE, NULL, 0x00,
4110 NULL, HFILL }
4112 {&hf_sccp_unknown_message,
4113 { "Unknown message", "sccp.unknown_message",
4114 FT_BYTES, BASE_NONE, NULL, 0x00,
4115 NULL, HFILL }
4117 {&hf_sccp_unknown_parameter,
4118 { "Unknown parameter", "sccp.unknown_parameter",
4119 FT_BYTES, BASE_NONE, NULL, 0x00,
4120 NULL, HFILL }
4124 /* Setup protocol subtree array */
4125 static int *ett[] = {
4126 &ett_sccp,
4127 &ett_sccp_called,
4128 &ett_sccp_called_ai,
4129 &ett_sccp_called_pc,
4130 &ett_sccp_called_gt,
4131 &ett_sccp_called_gt_digits,
4132 &ett_sccp_calling,
4133 &ett_sccp_calling_ai,
4134 &ett_sccp_calling_pc,
4135 &ett_sccp_calling_gt,
4136 &ett_sccp_calling_gt_digits,
4137 &ett_sccp_sequencing_segmenting,
4138 &ett_sccp_segmentation,
4139 &ett_sccp_ansi_isni_routing_control,
4140 &ett_sccp_xudt_msg_fragment,
4141 &ett_sccp_xudt_msg_fragments,
4142 &ett_sccp_assoc
4145 static ei_register_info ei[] = {
4146 { &ei_sccp_wrong_length, { "sccp.wrong_length", PI_MALFORMED, PI_ERROR, "Wrong length indicated.", EXPFILL }},
4147 { &ei_sccp_international_standard_address, { "sccp.international_standard_address", PI_MALFORMED, PI_WARN,
4148 "Address is coded to international standards. This doesn't normally happen in ANSI networks.", EXPFILL }},
4149 { &ei_sccp_no_ssn_present, { "sccp.ssn.not_present", PI_PROTOCOL, PI_WARN, "Message is routed on SSN, but SSN is not present", EXPFILL }},
4150 { &ei_sccp_ssn_zero, { "sccp.ssn.is_zero", PI_PROTOCOL, PI_WARN, "Message is routed on SSN, but SSN is zero (unspecified)", EXPFILL }},
4151 { &ei_sccp_class_unexpected, { "sccp.class_unexpected", PI_MALFORMED, PI_ERROR, "Unexpected message class for this message type", EXPFILL }},
4152 { &ei_sccp_handling_invalid, { "sccp.handling_invalid", PI_MALFORMED, PI_ERROR, "Invalid message handling", EXPFILL }},
4153 { &ei_sccp_gt_digits_missing, { "sccp.gt_digits_missing", PI_MALFORMED, PI_ERROR, "Address digits missing", EXPFILL }},
4154 { &ei_sccp_externally_reassembled, { "sccp.externally_reassembled", PI_ASSUMPTION, PI_NOTE, "Possibly externally reassembled (remaining length > 255 bytes), enable in SCCP preferences", EXPFILL }},
4157 /* Decode As handling */
4158 static build_valid_func sccp_da_build_value[1] = {sccp_value};
4159 static decode_as_value_t sccp_da_values = {sccp_prompt, 1, sccp_da_build_value};
4160 static decode_as_t sccp_da = {"sccp", "sccp.ssn", 1, 0, &sccp_da_values, NULL, NULL,
4161 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
4163 module_t *sccp_module;
4164 expert_module_t* expert_sccp;
4166 static uat_field_t users_flds[] = {
4167 UAT_FLD_DEC(sccp_users, ni, "Network Indicator", "Network Indicator"),
4168 UAT_FLD_RANGE(sccp_users, called_pc, "Called DPCs", 0xFFFFFF, "DPCs for which this protocol is to be used"),
4169 UAT_FLD_RANGE(sccp_users, called_ssn, "Called SSNs", 255, "Called SSNs for which this protocol is to be used"),
4170 UAT_FLD_VS(sccp_users, user, "User protocol", sccp_users_vals, "The User Protocol"),
4171 UAT_END_FIELDS
4175 uat_t *users_uat = uat_new("SCCP Users Table", sizeof(sccp_user_t),
4176 "sccp_users", true, &sccp_users,
4177 &num_sccp_users, UAT_AFFECTS_DISSECTION,
4178 "ChSccpUsers", sccp_users_copy_cb,
4179 sccp_users_update_cb, sccp_users_free_cb,
4180 NULL, NULL, users_flds );
4182 /* Register the protocol name and description */
4183 proto_sccp = proto_register_protocol("Signalling Connection Control Part", "SCCP", "sccp");
4185 sccp_handle = register_dissector("sccp", dissect_sccp, proto_sccp);
4187 /* Required function calls to register the header fields and subtrees used */
4188 proto_register_field_array(proto_sccp, hf, array_length(hf));
4189 proto_register_subtree_array(ett, array_length(ett));
4190 expert_sccp = expert_register_protocol(proto_sccp);
4191 expert_register_field_array(expert_sccp, ei, array_length(ei));
4193 sccp_ssn_dissector_table = register_dissector_table("sccp.ssn", "SCCP SSN", proto_sccp, FT_UINT8, BASE_DEC);
4195 heur_subdissector_list = register_heur_dissector_list_with_description("sccp", "SCCP Data fallback", proto_sccp);
4197 sccp_module = prefs_register_protocol(proto_sccp, proto_reg_handoff_sccp);
4199 prefs_register_uint_preference(sccp_module, "source_pc",
4200 "Source PC (in hex)",
4201 "The source point code (usually MSC) (to determine whether message is uplink or downlink)",
4202 16, &sccp_source_pc_global);
4204 prefs_register_bool_preference(sccp_module, "show_length", "Show length",
4205 "Show parameter length in the protocol tree",
4206 &sccp_show_length);
4208 prefs_register_bool_preference(sccp_module, "defragment_xudt",
4209 "Reassemble SCCP messages",
4210 "Whether SCCP messages should be reassembled",
4211 &sccp_reassemble);
4213 prefs_register_bool_preference(sccp_module, "trace_sccp",
4214 "Trace Associations",
4215 "Whether to keep information about messages and their associations",
4216 &trace_sccp);
4219 prefs_register_bool_preference(sccp_module, "show_more_info",
4220 "Show key parameters in Info Column",
4221 "Show SLR, DLR, and CAUSE Parameters in the Information Column of the Summary",
4222 &show_key_params);
4225 prefs_register_uat_preference(sccp_module, "users_table", "Users Table",
4226 "A table that enumerates user protocols to be used against specific PCs and SSNs",
4227 users_uat);
4229 prefs_register_bool_preference(sccp_module, "set_addresses", "Set source and destination GT addresses",
4230 "Set the source and destination addresses to the GT digits (if present)."
4231 " This may affect TCAP's ability to recognize which messages belong to which TCAP session.",
4232 &set_addresses);
4234 prefs_register_dissector_preference(sccp_module, "default_payload", "Default Payload",
4235 "The dissector which should be used to dissect the payload if nothing else has claimed it",
4236 &default_payload);
4238 prefs_register_bool_preference(sccp_module, "dt1_ignore_length", "Dissect data past 255 byte limit",
4239 "Use all bytes for data payload. Overcome 255 bytes limit of SCCP standard."
4240 " (Some tracing tools externally reassemble segmented data.)",
4241 &dt1_ignore_length);
4243 register_init_routine(&init_sccp);
4244 reassembly_table_register(&sccp_xudt_msg_reassembly_table,
4245 &addresses_reassembly_table_functions);
4247 assocs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
4249 sccp_reassembly_ids = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
4250 sccp_reassembly_id_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
4251 g_int64_hash, g_int64_equal);
4253 sccp_tap = register_tap("sccp");
4255 register_decode_as(&sccp_da);
4258 void
4259 proto_reg_handoff_sccp(void)
4261 static bool initialised = false;
4263 if (!initialised) {
4264 dissector_add_uint("wtap_encap", WTAP_ENCAP_SCCP, sccp_handle);
4265 dissector_add_uint("mtp3.service_indicator", MTP_SI_SCCP, sccp_handle);
4266 dissector_add_string("tali.opcode", "sccp", sccp_handle);
4268 data_handle = find_dissector("data");
4269 tcap_handle = find_dissector_add_dependency("tcap", proto_sccp);
4270 ranap_handle = find_dissector_add_dependency("ranap", proto_sccp);
4271 bssap_handle = find_dissector_add_dependency("bssap", proto_sccp);
4272 gsmmap_handle = find_dissector_add_dependency("gsm_map_sccp", proto_sccp);
4273 camel_handle = find_dissector_add_dependency("camel", proto_sccp);
4274 inap_handle = find_dissector_add_dependency("inap", proto_sccp);
4275 bsap_handle = find_dissector_add_dependency("bsap", proto_sccp);
4276 bssap_le_handle = find_dissector_add_dependency("bssap_le", proto_sccp);
4277 bssap_plus_handle = find_dissector_add_dependency("bssap_plus", proto_sccp);
4279 ss7pc_address_type = address_type_get_by_name("AT_SS7PC");
4281 initialised = true;
4282 hf_assoc_imsi = proto_registrar_get_id_byname("e212.assoc.imsi");
4285 default_handle = find_dissector(default_payload);
4289 * Editor modelines - https://www.wireshark.org/tools/modelines.html
4291 * Local Variables:
4292 * c-basic-offset: 2
4293 * tab-width: 8
4294 * indent-tabs-mode: nil
4295 * End:
4297 * ex: set shiftwidth=2 tabstop=8 expandtab:
4298 * :indentSize=2:tabSize=8:noTabs=true: