2 * Routines for Signalling Connection Control Part (SCCP) dissection
4 * It is hopefully compliant to:
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
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>
34 #include <epan/expert.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" },
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" },
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)" },
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
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" },
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" },
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" },
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" },
222 static const value_string sccp_ai_pci_values
[] = {
223 { 0x1, "Point Code present" },
224 { 0x0, "Point Code not present" },
227 static const value_string sccp_ai_ssni_values
[] = {
228 { 0x1, "SSN present" },
229 { 0x0, "SSN not present" },
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:
259 { 0x91, "GMLC(MAP)" },
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)" },
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" },
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" },
295 #define GT_OE_MASK 0x80
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" },
303 const value_string sccp_address_signal_values
[] = {
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" },
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)" },
372 /* Address signals above */
375 /* * * * * * * * * * * * * * * * *
376 * Global Title: ITU GTI == 0100 *
377 * * * * * * * * * * * * * * * * */
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" },
393 #define SEGMENTING_REASSEMBLING_LENGTH 1
394 #define SEGMENTING_REASSEMBLING_MASK 0x01
395 #define NO_MORE_DATA 0
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" },
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)" },
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)" },
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" },
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" },
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" },
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" },
529 static const value_string sccp_segmentation_class_values
[] = {
530 { 0, "Class 0 selected" },
531 { 1, "Class 1 selected" },
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" },
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" },
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" },
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 */
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;
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 */
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
{
765 dissector_handle_t
*handlep
;
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+"},
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" },
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
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
;
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
));
850 /* This is the last and only fragment, no need to reassembly anything. */
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
));
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.
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
);
882 return sccp_reassembly_get_id_pass2(pinfo
->num
, offset
);
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
;
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
);
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,
910 frags_id
, /* ID for fragments belonging together */
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
,
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
;
932 * There is only a single fragment, reassembly is not required.
934 new_tvb
= tvb_new_subset_length(tvb
, length_offset
+ 1, fragment_len
);
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 \
947 /*ws_warning("Frame %d not protocol %d @ line %d", frame_num, my_mtp3_standard, __LINE__);*/ \
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);
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))
974 gti
= (ai
& GTI_MASK
) >> GTI_SHIFT
;
975 if (my_mtp3_standard
== ANSI_STANDARD
) {
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
;
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))
996 /* Route on GT with no GT? */
997 if ((ri
== ROUTE_ON_GT
) && (gti
== AI_GTI_NO_GT
))
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
)
1007 len_needed
+= ADDRESS_SSN_LENGTH
;
1009 if (my_mtp3_standard
== ANSI_STANDARD
||
1010 my_mtp3_standard
== CHINESE_ITU_STANDARD
)
1011 len_needed
+= ANSI_PC_LENGTH
;
1013 len_needed
+= ITU_PC_LENGTH
;
1018 if (len_needed
> len
)
1025 looks_like_valid_sccp(uint32_t frame_num _U_
, tvbuff_t
*tvb
, uint8_t my_mtp3_standard
)
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...
1043 msgtype
= tvb_get_uint8(tvb
, SCCP_MSG_TYPE_OFFSET
);
1044 if (!try_val_to_str(msgtype
, sccp_message_type_acro_values
)) {
1047 offset
= SCCP_MSG_TYPE_LENGTH
;
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
+
1064 POINTER_LENGTH
> len
)
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
)
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
;
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
))
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
);
1109 called_ptr
= tvb_get_uint8(tvb
, offset
);
1110 if (called_ptr
== 0) /* Mandatory variable parameters must be present */
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
);
1118 calling_ptr
= tvb_get_uint8(tvb
, offset
);
1119 if (calling_ptr
== 0) /* Mandatory variable parameters must be present */
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
);
1127 data_ptr
= tvb_get_uint8(tvb
, offset
);
1128 if (data_ptr
== 0) /* Mandatory variable parameters must be present */
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 */
1150 /* Check that the variable pointers are within bounds */
1151 if (called_ptr
> len
|| calling_ptr
> len
|| data_ptr
> len
)
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
)
1158 if (msgtype
== SCCP_MSG_TYPE_LUDT
|| msgtype
== SCCP_MSG_TYPE_LUDTS
) {
1159 if (tvb_get_letohs(tvb
, data_ptr
)+data_ptr
> len
)
1162 if (tvb_get_uint8(tvb
, data_ptr
)+data_ptr
> len
)
1167 case SCCP_MSG_TYPE_CR
:
1169 if (len
< SCCP_MSG_TYPE_LENGTH
1170 + DESTINATION_LOCAL_REFERENCE_LENGTH
1171 + PROTOCOL_CLASS_LENGTH
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
);
1186 offset
+= PROTOCOL_CLASS_LENGTH
;
1187 data_ptr
= tvb_get_uint8(tvb
, offset
);
1191 offset
+= POINTER_LENGTH
;
1192 opt_ptr
= tvb_get_uint8(tvb
, offset
);
1196 offset
+= POINTER_LENGTH
;
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
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
);
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?
1230 /* If there are no optional parameters, are we at the end of the
1233 if ((opt_ptr
== 0) && (offset
!= len
))
1237 case SCCP_MSG_TYPE_CREF
:
1239 if (len
< SCCP_MSG_TYPE_LENGTH
1240 + DESTINATION_LOCAL_REFERENCE_LENGTH
1241 + REFUSAL_CAUSE_LENGTH
1245 offset
+= DESTINATION_LOCAL_REFERENCE_LENGTH
;
1247 cause
= tvb_get_uint8(tvb
, offset
);
1248 if (!try_val_to_str(cause
, sccp_refusal_cause_values
))
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?
1262 /* If there are no optional parameters, are we at the end of the
1265 if ((opt_ptr
== 0) && (offset
!= len
))
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
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
))
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?
1296 /* If there are no optional parameters, are we at the end of the
1299 if ((opt_ptr
== 0) && (offset
!= len
))
1303 case SCCP_MSG_TYPE_RLC
:
1305 if (len
!= SCCP_MSG_TYPE_LENGTH
1306 + DESTINATION_LOCAL_REFERENCE_LENGTH
1307 + SOURCE_LOCAL_REFERENCE_LENGTH
)
1311 case SCCP_MSG_TYPE_ERR
:
1313 if (len
!= SCCP_MSG_TYPE_LENGTH
1314 + DESTINATION_LOCAL_REFERENCE_LENGTH
1315 + ERROR_CAUSE_LENGTH
)
1318 offset
+= DESTINATION_LOCAL_REFERENCE_LENGTH
;
1320 cause
= tvb_get_uint8(tvb
, offset
);
1321 if (!try_val_to_str(cause
, sccp_error_cause_values
))
1325 case SCCP_MSG_TYPE_DT1
:
1327 if (len
< SCCP_MSG_TYPE_LENGTH
1328 + DESTINATION_LOCAL_REFERENCE_LENGTH
1329 + SEGMENTING_REASSEMBLING_LENGTH
1331 + PARAMETER_LENGTH_LENGTH
1332 + 1) /* At least 1 byte of payload */
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
)
1339 offset
+= SEGMENTING_REASSEMBLING_LENGTH
;
1341 data_ptr
= tvb_get_uint8(tvb
, offset
) + offset
;
1342 /* Verify the data pointer is within bounds */
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
)
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
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
);
1372 offset
+= PROTOCOL_CLASS_LENGTH
;
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 */
1386 DISSECTOR_ASSERT_NOT_REACHED();
1390 uint8_t param_len
= tvb_get_uint8(tvb
, called_ptr
);
1391 tvbuff_t
*param_tvb
;
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
)))
1402 uint8_t param_len
= tvb_get_uint8(tvb
, calling_ptr
);
1403 tvbuff_t
*param_tvb
;
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
)))
1416 opt_ptr
+= offset
-pointer_length
; /* (offset was already incremented) */
1418 /* Check that the optional pointer is within bounds */
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
))
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
))
1433 /* If we're at the end of the parameters, are we also at the end of the
1436 if ((opt_param
== PARAMETER_END_OF_OPTIONAL_PARAMETERS
) && ((opt_ptr
+1U) != len
))
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
;
1455 a
->payload
= SCCP_PLOAD_NONE
;
1456 a
->calling_party
= NULL
;
1457 a
->called_party
= NULL
;
1458 a
->extra_info
= NULL
;
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
;
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
;
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
) ) ) {
1541 if ( (value
->assoc
= (sccp_assoc_info_t
*)wmem_tree_lookup32_array(assocs
, fw_key
) ) ) {
1545 value
->assoc
= new_assoc(dpck
, opck
);
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;
1563 case SCCP_MSG_TYPE_IT
:
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
) ) ) {
1598 if ( (value
->assoc
= (sccp_assoc_info_t
*)wmem_tree_lookup32_array(assocs
, fw_key
) ) ) {
1602 value
->assoc
= new_assoc(dpck
, opck
);
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;
1621 wmem_tree_key_t key
[4];
1630 key
[2].key
= &value
->dlr
;
1636 value
->assoc
= (sccp_assoc_info_t
*)wmem_tree_lookup32_array(assocs
, key
);
1639 if (value
->assoc
->calling_dpc
== dpck
) {
1640 pinfo
->p2p_dir
= P2P_DIR_RECV
;
1642 pinfo
->p2p_dir
= P2P_DIR_SENT
;
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
) {
1664 for (m
= value
->assoc
->msgs
; m
->data
.co
.next
; m
= m
->data
.co
.next
) ;
1665 m
->data
.co
.next
= msg
;
1667 value
->assoc
->msgs
= msg
;
1670 value
->assoc
->curr_msg
= msg
;
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
;
1688 return value
->assoc
? value
->assoc
: &no_assoc
;
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"));
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"));
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
;
1717 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
1718 "Wrong length indicated. Expected 3, got %u", length
);
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
);
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
;
1737 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
1738 "Wrong length indicated. Expected 3, got %u", length
);
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
);
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
;
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
) {
1795 set_address(&pinfo
->dst
, AT_STRINGZ
, 1+(int)strlen(gt_digits
), gt_digits
);
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
));
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
;
1821 /* Shift GTI to where we can work with it */
1824 gt_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, length
,
1825 called
? ett_sccp_called_gt
: ett_sccp_calling_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... */
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
;
1888 expert_add_info(pinfo
, gt_item
, &ei_sccp_gt_digits_missing
);
1892 /* Decode address signal(s) */
1893 if (length
< offset
)
1896 signals_tvb
= tvb_new_subset_length(tvb
, offset
, (length
- offset
));
1898 digits_tree
= dissect_sccp_gt_address_information(signals_tvb
, pinfo
, gt_tree
,
1900 even
, called
, sccp_info
);
1902 /* Display the country code (if we can) */
1903 switch (np
>> GT_NP_SHIFT
) {
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
);
1910 case GT_NP_LAND_MOBILE
:
1911 dissect_e212_mcc_mnc_in_address(signals_tvb
, pinfo
, digits_tree
, 0);
1919 dissect_sccp_3byte_pc(tvbuff_t
*tvb
, proto_tree
*call_tree
, unsigned offset
,
1924 if (decode_mtp3_standard
== ANSI_STANDARD
)
1927 hf_pc
= hf_sccp_called_ansi_pc
;
1929 hf_pc
= hf_sccp_calling_ansi_pc
;
1930 } else /* CHINESE_ITU_STANDARD */ {
1932 hf_pc
= hf_sccp_called_chinese_pc
;
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
,
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
,
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
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.
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
;
1970 uint8_t national
= 0xFFU
, routing_ind
, gti
, pci
, ssni
, ssn
;
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
);
1992 expert_add_info(pinfo
, expert_item
, &ei_sccp_international_standard_address
);
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
||
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) */
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
);
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
);
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
);
2066 offset
= dissect_sccp_3byte_pc(tvb
, call_tree
, offset
, called
);
2071 /* Dissect SSN (if present) */
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
);
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
);
2121 } /* ssn_dissector */
2124 /* Dissect GT (if present) */
2125 if (gti
!= AI_GTI_NO_GT
) {
2126 if (length
< offset
)
2129 gt_tvb
= tvb_new_subset_length(tvb
, offset
, (length
- offset
));
2130 dissect_sccp_global_title(gt_tvb
, pinfo
, call_tree
, (length
- offset
), gti
,
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) */
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
);
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) */
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
)
2194 gt_tvb
= tvb_new_subset_length(tvb
, offset
, (length
- offset
));
2195 dissect_sccp_global_title(gt_tvb
, pinfo
, call_tree
, (length
- offset
), gti
,
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
);
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
);
2216 dissect_sccp_class_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned length
, sccp_decode_context_t
* sccp_info
)
2220 bool invalid_class
= false;
2223 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2224 "Wrong length indicated. Expected 1, got %u", length
);
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
:
2234 invalid_class
= true;
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
:
2243 invalid_class
= true;
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;
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;
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
);
2282 dissect_sccp_segmenting_reassembling_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned length
)
2285 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2286 "Wrong length indicated. Expected 1, got %u", length
);
2290 proto_tree_add_item(tree
, hf_sccp_more
, tvb
, 0, length
, ENC_BIG_ENDIAN
);
2294 dissect_sccp_receive_sequence_number_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned length
)
2297 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2298 "Wrong length indicated. Expected 1, got %u", length
);
2302 proto_tree_add_item(tree
, hf_sccp_rsn
, tvb
, 0, length
, ENC_NA
);
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
);
2325 dissect_sccp_credit_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned length
)
2328 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2329 "Wrong length indicated. Expected 1, got %u", length
);
2333 proto_tree_add_item(tree
, hf_sccp_credit
, tvb
, 0, length
, ENC_NA
);
2337 dissect_sccp_release_cause_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned length
)
2340 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2341 "Wrong length indicated. Expected 1, got %u", length
);
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));
2352 dissect_sccp_return_cause_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned length
)
2355 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2356 "Wrong length indicated. Expected 1, got %u", length
);
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));
2367 dissect_sccp_reset_cause_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned length
)
2370 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2371 "Wrong length indicated. Expected 1, got %u", length
);
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));
2382 dissect_sccp_error_cause_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned length
)
2385 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2386 "Wrong length indicated. Expected 1, got %u", length
);
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));
2397 dissect_sccp_refusal_cause_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned length
)
2400 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2401 "Wrong length indicated. Expected 1, got %u", length
);
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 */
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
;
2428 switch (pinfo
->p2p_dir
) {
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
;
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
;
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
;
2451 if ((num_sccp_users
) && (pinfo
->src
.type
== ss7pc_address_type
)) {
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
;
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
;
2474 call_tcap_dissector(handle
, tvb
, pinfo
, tree
);
2476 call_dissector_with_data(handle
, tvb
, pinfo
, tree
, sccp_info
);
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
)) {
2490 if ((other_ssn
!= INVALID_SSN
) && dissector_try_uint_with_data(sccp_ssn_dissector_table
, other_ssn
, tvb
, pinfo
, tree
, true, sccp_info
)) {
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
)) {
2499 /* try user default subdissector */
2500 if (default_handle
) {
2501 call_dissector_with_data(default_handle
, tvb
, pinfo
, tree
, sccp_info
);
2505 /* No sub-dissection occurred, treat it as raw data */
2506 call_dissector(data_handle
, tvb
, pinfo
, tree
);
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);
2529 proto_tree_add_item(param_tree
, hf_sccp_segmentation_slr
, tvb
, 1, length
-1, ENC_LITTLE_ENDIAN
);
2533 dissect_sccp_hop_counter_param(tvbuff_t
*tvb
, proto_tree
*tree
, unsigned length
)
2537 hops
= tvb_get_uint8(tvb
, 0);
2538 proto_tree_add_uint(tree
, hf_sccp_hop_counter
, tvb
, 0, length
, hops
);
2542 dissect_sccp_importance_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned length
)
2545 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2546 "Wrong length indicated. Expected 1, got %u", length
);
2550 proto_tree_add_item(tree
, hf_sccp_importance
, tvb
, 0, length
, ENC_NA
);
2554 dissect_sccp_isni_param(tvbuff_t
*tvb
, proto_tree
*tree
, unsigned length
)
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
);
2591 proto_tree_add_item(tree
, hf_sccp_ansi_isni_cluster
, tvb
, offset
,
2592 ANSI_NCM_LENGTH
, ENC_NA
);
2598 /* FUNCTION dissect_sccp_parameter():
2599 * Dissect a parameter given its type, offset into tvb, and length.
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).
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
);
2639 case PARAMETER_DESTINATION_LOCAL_REFERENCE
:
2640 dissect_sccp_dlr_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
, sccp_info
);
2643 case PARAMETER_SOURCE_LOCAL_REFERENCE
:
2644 dissect_sccp_slr_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
, sccp_info
);
2647 case PARAMETER_CALLED_PARTY_ADDRESS
:
2648 dissect_sccp_called_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
, sccp_info
);
2651 case PARAMETER_CALLING_PARTY_ADDRESS
:
2652 dissect_sccp_calling_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
, sccp_info
);
2655 case PARAMETER_CLASS
:
2656 dissect_sccp_class_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
, sccp_info
);
2659 case PARAMETER_SEGMENTING_REASSEMBLING
:
2660 dissect_sccp_segmenting_reassembling_param(parameter_tvb
, pinfo
, sccp_tree
,
2664 case PARAMETER_RECEIVE_SEQUENCE_NUMBER
:
2665 dissect_sccp_receive_sequence_number_param(parameter_tvb
, pinfo
, sccp_tree
,
2669 case PARAMETER_SEQUENCING_SEGMENTING
:
2670 dissect_sccp_sequencing_segmenting_param(parameter_tvb
, sccp_tree
,
2674 case PARAMETER_CREDIT
:
2675 dissect_sccp_credit_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2678 case PARAMETER_RELEASE_CAUSE
:
2679 dissect_sccp_release_cause_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2682 case PARAMETER_RETURN_CAUSE
:
2683 dissect_sccp_return_cause_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2686 case PARAMETER_RESET_CAUSE
:
2687 dissect_sccp_reset_cause_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2690 case PARAMETER_ERROR_CAUSE
:
2691 dissect_sccp_error_cause_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2694 case PARAMETER_REFUSAL_CAUSE
:
2695 dissect_sccp_refusal_cause_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
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
2711 case PARAMETER_SEGMENTATION
:
2712 dissect_sccp_segmentation_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2715 case PARAMETER_HOP_COUNTER
:
2716 dissect_sccp_hop_counter_param(parameter_tvb
, sccp_tree
, parameter_length
);
2719 case PARAMETER_IMPORTANCE
:
2720 if (decode_mtp3_standard
!= ANSI_STANDARD
)
2721 dissect_sccp_importance_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2723 dissect_sccp_unknown_param(parameter_tvb
, sccp_tree
, parameter_type
,
2727 case PARAMETER_LONG_DATA
:
2728 dissect_sccp_data_param(parameter_tvb
, pinfo
, tree
, sccp_info
->assoc
);
2731 case PARAMETER_ISNI
:
2732 if (decode_mtp3_standard
!= ANSI_STANDARD
)
2733 dissect_sccp_unknown_param(parameter_tvb
, sccp_tree
, parameter_type
,
2736 dissect_sccp_isni_param(parameter_tvb
, sccp_tree
, parameter_length
);
2740 dissect_sccp_unknown_param(parameter_tvb
, sccp_tree
, parameter_type
,
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).
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
;
2763 if (parameter_type
!= PARAMETER_LONG_DATA
) {
2764 parameter_length
= tvb_get_uint8(tvb
, offset
);
2765 length_length
= PARAMETER_LENGTH_LENGTH
;
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
,
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.
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
;
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
) {
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
);
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) \
2882 if (ptr_size == POINTER_LENGTH) \
2883 var = tvb_get_uint8(tvb, offset); \
2885 var = tvb_get_letohs(tvb, offset); \
2886 proto_tree_add_uint(sccp_tree, hf_var, tvb, \
2887 offset, ptr_size, var); \
2889 if (ptr_size == POINTER_LENGTH_LONG) \
2891 offset += ptr_size; \
2894 /* Macro for getting pointer to optional parameters */
2895 #define OPTIONAL_POINTER(ptr_size) \
2897 if (ptr_size == POINTER_LENGTH) \
2898 orig_opt_ptr = optional_pointer = tvb_get_uint8(tvb, offset); \
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; \
2910 /* Optional parameters are Segmentation and Importance
2911 * NOTE 2 - Segmentation Should not be present in case of a single XUDT
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
)
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
);
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
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)
2962 new_tvb
= sccp_reassemble_fragments(tvb
, pinfo
, tree
, variable_pointer3
, source_local_ref
, more_frag
);
2965 dissect_sccp_data_param(new_tvb
, pinfo
, tree
, sccp_info
->assoc
);
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
;
2978 dissect_sccp_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*sccp_tree
,
2981 uint16_t variable_pointer1
= 0, variable_pointer2
= 0, variable_pointer3
= 0;
2982 uint16_t optional_pointer
= 0, orig_opt_ptr
= 0;
2984 tvbuff_t
*new_tvb
= NULL
;
2985 uint32_t source_local_ref
= 0;
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"));
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
);
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
3052 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3053 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
3069 case SCCP_MSG_TYPE_CREF
:
3070 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3071 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
3084 case SCCP_MSG_TYPE_RLSD
:
3085 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3086 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
3103 case SCCP_MSG_TYPE_RLC
:
3104 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3105 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
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
,
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
);
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
);
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
);
3147 new_tvb
= sccp_reassemble_fragments(tvb
, pinfo
, tree
, variable_pointer1
, source_local_ref
, more
);
3151 dissect_sccp_data_param(new_tvb
, pinfo
, tree
, sccp_info
.assoc
);
3154 /* End reassemble */
3158 case SCCP_MSG_TYPE_DT2
:
3159 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3160 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
3177 case SCCP_MSG_TYPE_AK
:
3178 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3179 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
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
);
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
;
3249 case SCCP_MSG_TYPE_ED
:
3250 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3251 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
3264 case SCCP_MSG_TYPE_EA
:
3265 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3266 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
3273 case SCCP_MSG_TYPE_RSR
:
3274 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3275 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
3288 case SCCP_MSG_TYPE_RSC
:
3289 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3290 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
3300 case SCCP_MSG_TYPE_ERR
:
3301 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3302 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
3312 case SCCP_MSG_TYPE_IT
:
3313 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3314 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
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
);
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
);
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
;
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
);
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
);
3420 dissect_sccp_unknown_message(tvb
, sccp_tree
);
3424 dissect_sccp_optional_parameters(tvb
, pinfo
, sccp_tree
, tree
,
3425 optional_pointer
, &sccp_info
);
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
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
;
3450 decode_mtp3_standard
= (Standard_Type
)mtp3_standard
;
3453 /* Make entry in the Protocol column on summary display */
3454 switch (decode_mtp3_standard
) {
3456 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SCCP (Int. ITU)");
3459 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SCCP (ANSI)");
3461 case CHINESE_ITU_STANDARD
:
3462 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SCCP (Chin. ITU)");
3464 case JAPAN_STANDARD
:
3465 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SCCP (Japan)");
3469 /* In the interest of speed, if "tree" is NULL, don't do any work not
3470 necessary to generate protocol tree items. */
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
;
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
;
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
{
3512 dissector_handle_t
*handlep
;
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
},
3529 sccp_users_update_cb(void *r
, char **err
)
3531 sccp_user_t
*u
= (sccp_user_t
*)r
;
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
);
3542 if (ranges_are_equal(u
->called_ssn
, empty
)) {
3543 *err
= g_strdup("Must specify an SSN");
3544 wmem_free(NULL
, empty
);
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
;
3557 u
->uses_tcap
= false;
3558 u
->handlep
= &data_handle
;
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
;
3570 un
->uses_tcap
= u
->uses_tcap
;
3571 un
->handlep
= u
->handlep
;
3574 un
->called_pc
= range_copy(NULL
, u
->called_pc
);
3576 un
->called_ssn
= range_copy(NULL
, u
->called_ssn
);
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 **/
3602 sccp_reassembly_id_next
= 1;
3605 /* Register the protocol with Wireshark */
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,
3616 { &hf_sccp_variable_pointer1
,
3617 { "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1",
3618 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3621 { &hf_sccp_variable_pointer2
,
3622 { "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2",
3623 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3626 { &hf_sccp_variable_pointer3
,
3627 { "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3",
3628 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3631 { &hf_sccp_optional_pointer
,
3632 { "Pointer to Optional parameter", "sccp.optional_pointer",
3633 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3636 { &hf_sccp_param_length
,
3637 { "Variable parameter length", "sccp.parameter_length",
3638 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3642 { "Called or Calling SubSystem Number", "sccp.ssn",
3643 FT_UINT8
, BASE_DEC
, VALS(sccp_ssn_values
), 0x0,
3646 { &hf_sccp_gt_digits
,
3647 { "Called or Calling GT Digits", "sccp.digits",
3648 FT_STRING
, BASE_NONE
, NULL
, 0x0,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
3696 { &hf_sccp_called_ssn
,
3697 { "SubSystem Number", "sccp.called.ssn",
3698 FT_UINT8
, BASE_DEC
, VALS(sccp_ssn_values
), 0x0,
3701 { &hf_sccp_called_itu_pc
,
3702 { "PC", "sccp.called.pc",
3703 FT_UINT16
, BASE_DEC
, NULL
, ITU_PC_MASK
,
3706 { &hf_sccp_called_ansi_pc
,
3707 { "PC", "sccp.called.ansi_pc",
3708 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3711 { &hf_sccp_called_chinese_pc
,
3712 { "PC", "sccp.called.chinese_pc",
3713 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3716 { &hf_sccp_called_japan_pc
,
3717 { "PC", "sccp.called.pc",
3718 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3721 { &hf_sccp_called_pc_network
,
3722 { "PC Network", "sccp.called.network",
3723 FT_UINT24
, BASE_DEC
, NULL
, ANSI_NETWORK_MASK
,
3726 { &hf_sccp_called_pc_cluster
,
3727 { "PC Cluster", "sccp.called.cluster",
3728 FT_UINT24
, BASE_DEC
, NULL
, ANSI_CLUSTER_MASK
,
3731 { &hf_sccp_called_pc_member
,
3732 { "PC Member", "sccp.called.member",
3733 FT_UINT24
, BASE_DEC
, NULL
, ANSI_MEMBER_MASK
,
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
,
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
,
3746 { &hf_sccp_called_gt_tt
,
3747 { "Translation Type", "sccp.called.tt",
3748 FT_UINT8
, BASE_HEX_DEC
, NULL
, 0x0,
3751 { &hf_sccp_called_gt_np
,
3752 { "Numbering Plan", "sccp.called.np",
3753 FT_UINT8
, BASE_HEX
, VALS(sccp_np_values
), GT_NP_MASK
,
3756 { &hf_sccp_called_gt_es
,
3757 { "Encoding Scheme", "sccp.called.es",
3758 FT_UINT8
, BASE_HEX
, VALS(sccp_es_values
), GT_ES_MASK
,
3761 { &hf_sccp_called_gt_digits
,
3762 { "Called Party Digits", "sccp.called.digits",
3763 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3766 { &hf_sccp_called_gt_digits_length
,
3767 { "Number of Called Party Digits", "sccp.called.digits.length",
3768 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
3816 { &hf_sccp_calling_ssn
,
3817 { "SubSystem Number", "sccp.calling.ssn",
3818 FT_UINT8
, BASE_DEC
, VALS(sccp_ssn_values
), 0x0,
3821 { &hf_sccp_calling_itu_pc
,
3822 { "PC", "sccp.calling.pc",
3823 FT_UINT16
, BASE_DEC
, NULL
, ITU_PC_MASK
,
3826 { &hf_sccp_calling_ansi_pc
,
3827 { "PC", "sccp.calling.ansi_pc",
3828 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3831 { &hf_sccp_calling_chinese_pc
,
3832 { "PC", "sccp.calling.chinese_pc",
3833 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3836 { &hf_sccp_calling_japan_pc
,
3837 { "PC", "sccp.calling.pc",
3838 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3841 { &hf_sccp_calling_pc_network
,
3842 { "PC Network", "sccp.calling.network",
3843 FT_UINT24
, BASE_DEC
, NULL
, ANSI_NETWORK_MASK
,
3846 { &hf_sccp_calling_pc_cluster
,
3847 { "PC Cluster", "sccp.calling.cluster",
3848 FT_UINT24
, BASE_DEC
, NULL
, ANSI_CLUSTER_MASK
,
3851 { &hf_sccp_calling_pc_member
,
3852 { "PC Member", "sccp.calling.member",
3853 FT_UINT24
, BASE_DEC
, NULL
, ANSI_MEMBER_MASK
,
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
,
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
,
3866 { &hf_sccp_calling_gt_tt
,
3867 { "Translation Type", "sccp.calling.tt",
3868 FT_UINT8
, BASE_HEX_DEC
, NULL
, 0x0,
3871 { &hf_sccp_calling_gt_np
,
3872 { "Numbering Plan", "sccp.calling.np",
3873 FT_UINT8
, BASE_HEX
, VALS(sccp_np_values
), GT_NP_MASK
,
3876 { &hf_sccp_calling_gt_es
,
3877 { "Encoding Scheme", "sccp.calling.es",
3878 FT_UINT8
, BASE_HEX
, VALS(sccp_es_values
), GT_ES_MASK
,
3881 { &hf_sccp_calling_gt_digits
,
3882 { "Calling Party Digits", "sccp.calling.digits",
3883 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3886 { &hf_sccp_calling_gt_digits_length
,
3887 { "Number of Calling Party Digits", "sccp.calling.digits.length",
3888 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3892 { "Destination Local Reference", "sccp.dlr",
3893 FT_UINT24
, BASE_HEX
, NULL
, 0x0,
3897 { "Source Local Reference", "sccp.slr",
3898 FT_UINT24
, BASE_HEX
, NULL
, 0x0,
3902 { "Local Reference", "sccp.lr",
3903 FT_UINT24
, BASE_HEX
, NULL
, 0x0,
3907 { "Class", "sccp.class",
3908 FT_UINT8
, BASE_HEX
, NULL
, CLASS_CLASS_MASK
,
3911 { &hf_sccp_handling
,
3912 { "Message handling", "sccp.handling",
3913 FT_UINT8
, BASE_HEX
, VALS(sccp_class_handling_values
), CLASS_SPARE_HANDLING_MASK
,
3917 { "More data", "sccp.more",
3918 FT_UINT8
, BASE_HEX
, VALS(sccp_segmenting_reassembling_values
), SEGMENTING_REASSEMBLING_MASK
,
3922 { "Receive Sequence Number", "sccp.rsn",
3923 FT_UINT8
, BASE_HEX
, NULL
, RSN_MASK
,
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
,
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
,
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
,
3942 { "Credit", "sccp.credit",
3943 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3946 { &hf_sccp_release_cause
,
3947 { "Release Cause", "sccp.release_cause",
3948 FT_UINT8
, BASE_HEX
, VALS(sccp_release_cause_values
), 0x0,
3951 { &hf_sccp_return_cause
,
3952 { "Return Cause", "sccp.return_cause",
3953 FT_UINT8
, BASE_HEX
, VALS(sccp_return_cause_values
), 0x0,
3956 { &hf_sccp_reset_cause
,
3957 { "Reset Cause", "sccp.reset_cause",
3958 FT_UINT8
, BASE_HEX
, VALS(sccp_reset_cause_values
), 0x0,
3961 { &hf_sccp_error_cause
,
3962 { "Error Cause", "sccp.error_cause",
3963 FT_UINT8
, BASE_HEX
, VALS(sccp_error_cause_values
), 0x0,
3966 { &hf_sccp_refusal_cause
,
3967 { "Refusal Cause", "sccp.refusal_cause",
3968 FT_UINT8
, BASE_HEX
, VALS(sccp_refusal_cause_values
), 0x0,
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
,
3976 { &hf_sccp_segmentation_class
,
3977 { "Segmentation: Class", "sccp.segmentation.class",
3978 FT_UINT8
, BASE_HEX
, VALS(sccp_segmentation_class_values
), SEGMENTATION_CLASS_MASK
,
3981 { &hf_sccp_segmentation_remaining
,
3982 { "Segmentation: Remaining", "sccp.segmentation.remaining",
3983 FT_UINT8
, BASE_HEX
, NULL
, SEGMENTATION_REMAINING_MASK
,
3986 { &hf_sccp_segmentation_slr
,
3987 { "Segmentation: Source Local Reference", "sccp.segmentation.slr",
3988 FT_UINT24
, BASE_HEX
, NULL
, 0x0,
3991 { &hf_sccp_hop_counter
,
3992 { "Hop Counter", "sccp.hops",
3993 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3996 { &hf_sccp_importance
,
3997 { "Importance", "sccp.importance",
3998 FT_UINT8
, BASE_HEX
, NULL
, IMPORTANCE_IMPORTANCE_MASK
,
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
,
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
,
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
,
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
,
4022 { &hf_sccp_ansi_isni_counter
,
4023 { "ISNI Counter", "sccp.isni.counter",
4024 FT_UINT8
, BASE_DEC
, NULL
, ANSI_ISNI_COUNTER_MASK
,
4027 { &hf_sccp_ansi_isni_network
,
4028 { "Network ID network", "sccp.isni.network",
4029 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
4032 { &hf_sccp_ansi_isni_cluster
,
4033 { "Network ID cluster", "sccp.isni.cluster",
4034 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
4037 {&hf_sccp_xudt_msg_fragments
,
4038 { "Message fragments", "sccp.msg.fragments",
4039 FT_NONE
, BASE_NONE
, NULL
, 0x00,
4042 {&hf_sccp_xudt_msg_fragment
,
4043 { "Message fragment", "sccp.msg.fragment",
4044 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
4047 {&hf_sccp_xudt_msg_fragment_overlap
,
4048 { "Message fragment overlap", "sccp.msg.fragment.overlap",
4049 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
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,
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,
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,
4067 {&hf_sccp_xudt_msg_fragment_error
,
4068 { "Message defragmentation error", "sccp.msg.fragment.error",
4069 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
4072 {&hf_sccp_xudt_msg_fragment_count
,
4073 { "Message fragment count", "sccp.msg.fragment.count",
4074 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
4077 {&hf_sccp_xudt_msg_reassembled_in
,
4078 { "Reassembled in", "sccp.msg.reassembled.in",
4079 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
4082 {&hf_sccp_xudt_msg_reassembled_length
,
4083 { "Reassembled SCCP length", "sccp.msg.reassembled.length",
4084 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
4087 { &hf_sccp_assoc_id
,
4088 { "Association ID", "sccp.assoc.id",
4089 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4092 {&hf_sccp_assoc_msg
,
4093 { "Message in frame", "sccp.assoc.msg",
4094 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
4097 {&hf_sccp_segmented_data
,
4098 { "Segmented Data", "sccp.segmented_data",
4099 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
4102 {&hf_sccp_linked_dissector
,
4103 { "Linked dissector", "sccp.linked_dissector",
4104 FT_STRING
, BASE_NONE
, NULL
, 0x00,
4107 {&hf_sccp_end_optional_param
,
4108 { "End of Optional", "sccp.end_optional_param",
4109 FT_NONE
, BASE_NONE
, NULL
, 0x00,
4112 {&hf_sccp_unknown_message
,
4113 { "Unknown message", "sccp.unknown_message",
4114 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
4117 {&hf_sccp_unknown_parameter
,
4118 { "Unknown parameter", "sccp.unknown_parameter",
4119 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
4124 /* Setup protocol subtree array */
4125 static int *ett
[] = {
4128 &ett_sccp_called_ai
,
4129 &ett_sccp_called_pc
,
4130 &ett_sccp_called_gt
,
4131 &ett_sccp_called_gt_digits
,
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
,
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"),
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",
4208 prefs_register_bool_preference(sccp_module
, "defragment_xudt",
4209 "Reassemble SCCP messages",
4210 "Whether SCCP messages should be reassembled",
4213 prefs_register_bool_preference(sccp_module
, "trace_sccp",
4214 "Trace Associations",
4215 "Whether to keep information about messages and their associations",
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",
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",
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.",
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",
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
);
4259 proto_reg_handoff_sccp(void)
4261 static bool initialised
= false;
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");
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
4294 * indent-tabs-mode: nil
4297 * ex: set shiftwidth=2 tabstop=8 expandtab:
4298 * :indentSize=2:tabSize=8:noTabs=true: