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>
17 * Wireshark - Network traffic analyzer
18 * By Gerald Combs <gerald@wireshark.org>
19 * Copyright 1998 Gerald Combs
21 * Copied from packet-m2pa.c
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * as published by the Free Software Foundation; either version 2
26 * of the License, or (at your option) any later version.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
45 #include <epan/packet.h>
46 #include <epan/prefs.h>
47 #include <epan/emem.h>
48 #include <epan/wmem/wmem.h>
49 #include <epan/reassemble.h>
50 #include <epan/asn1.h>
52 #include <epan/strutil.h>
53 #include <epan/expert.h>
56 #include "packet-mtp3.h"
57 #include "packet-tcap.h"
58 #include "packet-sccp.h"
59 #include "packet-e164.h"
60 #include "packet-e212.h"
61 #include "packet-frame.h"
63 /* function prototypes */
64 void proto_reg_handoff_sccp(void);
66 static Standard_Type decode_mtp3_standard
;
68 #define SCCP_MSG_TYPE_OFFSET 0
69 #define SCCP_MSG_TYPE_LENGTH 1
70 #define POINTER_LENGTH 1
71 #define POINTER_LENGTH_LONG 2
73 #define INVALID_LR 0xffffff /* a reserved value */
75 /* Same as below but with names typed out */
76 static const value_string sccp_message_type_values
[] = {
77 { SCCP_MSG_TYPE_CR
, "Connection Request" },
78 { SCCP_MSG_TYPE_CC
, "Connection Confirm" },
79 { SCCP_MSG_TYPE_CREF
, "Connection Refused" },
80 { SCCP_MSG_TYPE_RLSD
, "Released" },
81 { SCCP_MSG_TYPE_RLC
, "Release Complete" },
82 { SCCP_MSG_TYPE_DT1
, "Data Form 1" },
83 { SCCP_MSG_TYPE_DT2
, "Data Form 2" },
84 { SCCP_MSG_TYPE_AK
, "Data Acknowledgement" },
85 { SCCP_MSG_TYPE_UDT
, "Unitdata" },
86 { SCCP_MSG_TYPE_UDTS
, "Unitdata Service" },
87 { SCCP_MSG_TYPE_ED
, "Expedited Data" },
88 { SCCP_MSG_TYPE_EA
, "Expedited Data Acknowledgement" },
89 { SCCP_MSG_TYPE_RSR
, "Reset Request" },
90 { SCCP_MSG_TYPE_RSC
, "Reset Confirmation" },
91 { SCCP_MSG_TYPE_ERR
, "Error" },
92 { SCCP_MSG_TYPE_IT
, "Inactivity Timer" },
93 { SCCP_MSG_TYPE_XUDT
, "Extended Unitdata" },
94 { SCCP_MSG_TYPE_XUDTS
, "Extended Unitdata Service" },
95 { SCCP_MSG_TYPE_LUDT
, "Long Unitdata" },
96 { SCCP_MSG_TYPE_LUDTS
, "Long Unitdata Service" },
99 /* Same as above but in acronym form (for the Info column) */
100 const value_string sccp_message_type_acro_values
[] = {
101 { SCCP_MSG_TYPE_CR
, "CR" },
102 { SCCP_MSG_TYPE_CC
, "CC" },
103 { SCCP_MSG_TYPE_CREF
, "CREF" },
104 { SCCP_MSG_TYPE_RLSD
, "RLSD" },
105 { SCCP_MSG_TYPE_RLC
, "RLC" },
106 { SCCP_MSG_TYPE_DT1
, "DT1" },
107 { SCCP_MSG_TYPE_DT2
, "DT2" },
108 { SCCP_MSG_TYPE_AK
, "AK" },
109 { SCCP_MSG_TYPE_UDT
, "UDT" },
110 { SCCP_MSG_TYPE_UDTS
, "UDTS" },
111 { SCCP_MSG_TYPE_ED
, "ED" },
112 { SCCP_MSG_TYPE_EA
, "EA" },
113 { SCCP_MSG_TYPE_RSR
, "RSR" },
114 { SCCP_MSG_TYPE_RSC
, "RSC" },
115 { SCCP_MSG_TYPE_ERR
, "ERR" },
116 { SCCP_MSG_TYPE_IT
, "IT" },
117 { SCCP_MSG_TYPE_XUDT
, "XUDT" },
118 { SCCP_MSG_TYPE_XUDTS
, "XUDTS" },
119 { SCCP_MSG_TYPE_LUDT
, "LUDT" },
120 { SCCP_MSG_TYPE_LUDTS
, "LUDTS" },
123 #define PARAMETER_LENGTH_LENGTH 1
124 #define PARAMETER_LONG_DATA_LENGTH_LENGTH 2
125 #define PARAMETER_TYPE_LENGTH 1
127 #define PARAMETER_END_OF_OPTIONAL_PARAMETERS 0x00
128 #define PARAMETER_DESTINATION_LOCAL_REFERENCE 0x01
129 #define PARAMETER_SOURCE_LOCAL_REFERENCE 0x02
130 #define PARAMETER_CALLED_PARTY_ADDRESS 0x03
131 #define PARAMETER_CALLING_PARTY_ADDRESS 0x04
132 #define PARAMETER_CLASS 0x05
133 #define PARAMETER_SEGMENTING_REASSEMBLING 0x06
134 #define PARAMETER_RECEIVE_SEQUENCE_NUMBER 0x07
135 #define PARAMETER_SEQUENCING_SEGMENTING 0x08
136 #define PARAMETER_CREDIT 0x09
137 #define PARAMETER_RELEASE_CAUSE 0x0a
138 #define PARAMETER_RETURN_CAUSE 0x0b
139 #define PARAMETER_RESET_CAUSE 0x0c
140 #define PARAMETER_ERROR_CAUSE 0x0d
141 #define PARAMETER_REFUSAL_CAUSE 0x0e
142 #define PARAMETER_DATA 0x0f
143 #define PARAMETER_SEGMENTATION 0x10
144 #define PARAMETER_HOP_COUNTER 0x11
145 /* Importance is ITU only */
146 #define PARAMETER_IMPORTANCE 0x12
147 #define PARAMETER_LONG_DATA 0x13
148 /* ISNI is ANSI only */
149 #define PARAMETER_ISNI 0xfa
151 static const value_string sccp_parameter_values
[] = {
152 { PARAMETER_END_OF_OPTIONAL_PARAMETERS
, "End of Optional Parameters" },
153 { PARAMETER_DESTINATION_LOCAL_REFERENCE
, "Destination Local Reference" },
154 { PARAMETER_SOURCE_LOCAL_REFERENCE
, "Source Local Reference" },
155 { PARAMETER_CALLED_PARTY_ADDRESS
, "Called Party Address" },
156 { PARAMETER_CALLING_PARTY_ADDRESS
, "Calling Party Address" },
157 { PARAMETER_CLASS
, "Protocol Class" },
158 { PARAMETER_SEGMENTING_REASSEMBLING
, "Segmenting/Reassembling" },
159 { PARAMETER_RECEIVE_SEQUENCE_NUMBER
, "Receive Sequence Number" },
160 { PARAMETER_SEQUENCING_SEGMENTING
, "Sequencing/Segmenting" },
161 { PARAMETER_CREDIT
, "Credit" },
162 { PARAMETER_RELEASE_CAUSE
, "Release Cause" },
163 { PARAMETER_RETURN_CAUSE
, "Return Cause" },
164 { PARAMETER_RESET_CAUSE
, "Reset Cause" },
165 { PARAMETER_ERROR_CAUSE
, "Error Cause" },
166 { PARAMETER_REFUSAL_CAUSE
, "Refusal Cause" },
167 { PARAMETER_DATA
, "Data" },
168 { PARAMETER_SEGMENTATION
, "Segmentation" },
169 { PARAMETER_HOP_COUNTER
, "Hop Counter" },
170 { PARAMETER_IMPORTANCE
, "Importance (ITU)" },
171 { PARAMETER_LONG_DATA
, "Long Data" },
172 { PARAMETER_ISNI
, "Intermediate Signaling Network Identification (ANSI)" },
176 #define END_OF_OPTIONAL_PARAMETERS_LENGTH 1
177 #define DESTINATION_LOCAL_REFERENCE_LENGTH 3
178 #define SOURCE_LOCAL_REFERENCE_LENGTH 3
179 #define PROTOCOL_CLASS_LENGTH 1
180 #define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
181 #define CREDIT_LENGTH 1
182 #define RELEASE_CAUSE_LENGTH 1
183 #define RETURN_CAUSE_LENGTH 1
184 #define RESET_CAUSE_LENGTH 1
185 #define ERROR_CAUSE_LENGTH 1
186 #define REFUSAL_CAUSE_LENGTH 1
187 #define HOP_COUNTER_LENGTH 1
188 #define IMPORTANCE_LENGTH 1
191 /* Parts of the Called and Calling Address parameters */
192 /* Address Indicator */
193 #define ADDRESS_INDICATOR_LENGTH 1
194 #define ITU_RESERVED_MASK 0x80
195 #define ANSI_NATIONAL_MASK 0x80
196 #define ROUTING_INDICATOR_MASK 0x40
197 #define GTI_MASK 0x3C
199 #define ITU_SSN_INDICATOR_MASK 0x02
200 #define ITU_PC_INDICATOR_MASK 0x01
201 #define ANSI_PC_INDICATOR_MASK 0x02
202 #define ANSI_SSN_INDICATOR_MASK 0x01
204 static const value_string sccp_ansi_national_indicator_values
[] = {
205 { 0x0, "Address coded to International standard" },
206 { 0x1, "Address coded to National standard" },
209 #define ROUTE_ON_GT 0x0
210 #define ROUTE_ON_SSN 0x1
211 #define ROUTING_INDICATOR_SHIFT 6
212 static const value_string sccp_routing_indicator_values
[] = {
213 { ROUTE_ON_GT
, "Route on GT" },
214 { ROUTE_ON_SSN
, "Route on SSN" },
217 #define AI_GTI_NO_GT 0x0
218 #define ITU_AI_GTI_NAI 0x1
219 #define AI_GTI_TT 0x2
220 #define ITU_AI_GTI_TT_NP_ES 0x3
221 #define ITU_AI_GTI_TT_NP_ES_NAI 0x4
222 static const value_string sccp_itu_global_title_indicator_values
[] = {
223 { AI_GTI_NO_GT
, "No Global Title" },
224 { ITU_AI_GTI_NAI
, "Nature of Address Indicator only" },
225 { AI_GTI_TT
, "Translation Type only" },
226 { ITU_AI_GTI_TT_NP_ES
, "Translation Type, Numbering Plan, and Encoding Scheme included" },
227 { ITU_AI_GTI_TT_NP_ES_NAI
, "Translation Type, Numbering Plan, Encoding Scheme, and Nature of Address Indicator included" },
230 /* #define AI_GTI_NO_GT 0x0 */
231 #define ANSI_AI_GTI_TT_NP_ES 0x1
232 /* #define AI_GTI_TT 0x2 */
233 static const value_string sccp_ansi_global_title_indicator_values
[] = {
234 { AI_GTI_NO_GT
, "No Global Title" },
235 { ANSI_AI_GTI_TT_NP_ES
, "Translation Type, Numbering Plan, and Encoding Scheme included" },
236 { AI_GTI_TT
, "Translation Type only" },
239 static const value_string sccp_ai_pci_values
[] = {
240 { 0x1, "Point Code present" },
241 { 0x0, "Point Code not present" },
244 static const value_string sccp_ai_ssni_values
[] = {
245 { 0x1, "SSN present" },
246 { 0x0, "SSN not present" },
249 #define ADDRESS_SSN_LENGTH 1
250 #define INVALID_SSN 0xff
251 /* Some values from 3GPP TS 23.003 */
252 /* Japan TTC and NTT define a lot of SSNs, some of which conflict with
253 * these. They are not added for now.
255 static const value_string sccp_ssn_values
[] = {
256 { 0x00, "SSN not known/not used" },
257 { 0x01, "SCCP management" },
258 { 0x02, "Reserved for ITU-T allocation" },
259 { 0x03, "ISDN User Part" },
260 { 0x04, "OMAP (Operation, Maintenance, and Administration Part)" },
261 { 0x05, "MAP (Mobile Application Part)" },
262 { 0x06, "HLR (Home Location Register)" },
263 { 0x07, "VLR (Visitor Location Register)" },
264 { 0x08, "MSC (Mobile Switching Center)" },
265 { 0x09, "EIC/EIR (Equipment Identifier Center/Equipment Identification Register)" },
266 { 0x0a, "AUC/AC (Authentication Center)" },
267 { 0x0b, "ISDN supplementary services (ITU only)" },
268 { 0x0c, "Reserved for international use (ITU only)" },
269 { 0x0d, "Broadband ISDN edge-to-edge applications (ITU only)" },
270 { 0x0e, "TC test responder (ITU only)" },
271 /* The following national network subsystem numbers have been allocated for use within and
272 * between GSM/UMTS networks:
276 { 0x91, "GMLC(MAP)" },
278 { 0x93, "gsmSCF (MAP) or IM-SSF (MAP) or Presence Network Agent" },
279 { 0x94, "SIWF (MAP)" },
280 { 0x95, "SGSN (MAP)" },
281 { 0x96, "GGSN (MAP)" },
282 /* The following national network subsystem numbers have been allocated for use within GSM/UMTS networks:*/
284 { 0xfa, "BSC (BSSAP-LE)" },
285 { 0xfb, "MSC (BSSAP-LE)" },
286 { 0xfc, "IOS or SMLC (BSSAP-LE)" },
287 { 0xfd, "BSS O&M (A interface)" },
288 { 0xfe, "BSSAP/BSAP" },
292 /* * * * * * * * * * * * * * * * *
293 * Global Title: ITU GTI == 0001 *
294 * * * * * * * * * * * * * * * * */
295 #define GT_NAI_MASK 0x7F
296 #define GT_NAI_LENGTH 1
297 #define GT_NAI_UNKNOWN 0x00
298 #define GT_NAI_SUBSCRIBER_NUMBER 0x01
299 #define GT_NAI_RESERVED_NATIONAL 0x02
300 #define GT_NAI_NATIONAL_SIG_NUM 0x03
301 #define GT_NAI_INTERNATIONAL_NUM 0x04
302 static const value_string sccp_nai_values
[] = {
303 { GT_NAI_UNKNOWN
, "NAI unknown" },
304 { GT_NAI_SUBSCRIBER_NUMBER
, "Subscriber Number" },
305 { GT_NAI_RESERVED_NATIONAL
, "Reserved for national use" },
306 { GT_NAI_NATIONAL_SIG_NUM
, "National significant number" },
307 { GT_NAI_INTERNATIONAL_NUM
, "International number" },
311 #define GT_OE_MASK 0x80
314 static const value_string sccp_oe_values
[] = {
315 { GT_OE_EVEN
, "Even number of address signals" },
316 { GT_OE_ODD
, "Odd number of address signals" },
319 const value_string sccp_address_signal_values
[] = {
339 /* * * * * * * * * * * * * * * * * * * * *
340 * Global Title: ITU and ANSI GTI == 0010 *
341 * * * * * * * * * * * * * * * * * * * * */
342 #define GT_TT_LENGTH 1
345 /* * * * * * * * * * * * * * * * * * * * * * * * * *
346 * Global Title: ITU GTI == 0011, ANSI GTI == 0001 *
347 * * * * * * * * * * * * * * * * * * * * * * * * * */
348 #define GT_NP_MASK 0xf0
349 #define GT_NP_SHIFT 4
350 #define GT_NP_ES_LENGTH 1
351 #define GT_NP_UNKNOWN 0x00
352 #define GT_NP_ISDN 0x01
353 #define GT_NP_GENERIC_RESERVED 0x02
354 #define GT_NP_DATA 0x03
355 #define GT_NP_TELEX 0x04
356 #define GT_NP_MARITIME_MOBILE 0x05
357 #define GT_NP_LAND_MOBILE 0x06
358 #define GT_NP_ISDN_MOBILE 0x07
359 #define GT_NP_PRIVATE_NETWORK 0x0e
360 #define GT_NP_RESERVED 0x0f
361 static const value_string sccp_np_values
[] = {
362 { GT_NP_UNKNOWN
, "Unknown" },
363 { GT_NP_ISDN
, "ISDN/telephony" },
364 { GT_NP_GENERIC_RESERVED
, "Generic (ITU)/Reserved (ANSI)" },
365 { GT_NP_DATA
, "Data" },
366 { GT_NP_TELEX
, "Telex" },
367 { GT_NP_MARITIME_MOBILE
, "Maritime mobile" },
368 { GT_NP_LAND_MOBILE
, "Land mobile" },
369 { GT_NP_ISDN_MOBILE
, "ISDN/mobile" },
370 { GT_NP_PRIVATE_NETWORK
, "Private network or network-specific" },
371 { GT_NP_RESERVED
, "Reserved" },
374 #define GT_ES_MASK 0x0f
375 #define GT_ES_UNKNOWN 0x0
376 #define GT_ES_BCD_ODD 0x1
377 #define GT_ES_BCD_EVEN 0x2
378 #define GT_ES_NATIONAL 0x3
379 #define GT_ES_RESERVED 0xf
380 static const value_string sccp_es_values
[] = {
381 { GT_ES_UNKNOWN
, "Unknown" },
382 { GT_ES_BCD_ODD
, "BCD, odd number of digits" },
383 { GT_ES_BCD_EVEN
, "BCD, even number of digits" },
384 { GT_ES_NATIONAL
, "National specific" },
385 { GT_ES_RESERVED
, "Reserved (ITU)/Spare (ANSI)" },
388 /* Address signals above */
391 /* * * * * * * * * * * * * * * * *
392 * Global Title: ITU GTI == 0100 *
393 * * * * * * * * * * * * * * * * */
397 /* Address signals above */
400 #define CLASS_CLASS_MASK 0xf
401 #define CLASS_SPARE_HANDLING_MASK 0xf0
402 #define CLASS_SPARE_HANDLING_SHIFT 4
403 static const value_string sccp_class_handling_values
[] = {
404 { 0x0, "No special options" },
405 { 0x8, "Return message on error" },
409 #define SEGMENTING_REASSEMBLING_LENGTH 1
410 #define SEGMENTING_REASSEMBLING_MASK 0x01
411 #define NO_MORE_DATA 0
413 /* This is also used by sequencing-segmenting parameter */
414 static const value_string sccp_segmenting_reassembling_values
[] = {
415 { NO_MORE_DATA
, "No more data" },
416 { MORE_DATA
, "More data" },
420 #define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
421 #define RSN_MASK 0xfe
423 #define SEQUENCING_SEGMENTING_LENGTH 2
424 #define SEQUENCING_SEGMENTING_SSN_LENGTH 1
425 #define SEQUENCING_SEGMENTING_RSN_LENGTH 1
426 #define SEND_SEQUENCE_NUMBER_MASK 0xfe
427 #define RECEIVE_SEQUENCE_NUMBER_MASK 0xfe
428 #define SEQUENCING_SEGMENTING_MORE_MASK 0x01
431 #define CREDIT_LENGTH 1
433 #define RELEASE_CAUSE_LENGTH 1
434 const value_string sccp_release_cause_values
[] = {
435 { 0x00, "End user originated" },
436 { 0x01, "End user congestion" },
437 { 0x02, "End user failure" },
438 { 0x03, "SCCP user originated" },
439 { 0x04, "Remote procedure error" },
440 { 0x05, "Inconsistent connection data" },
441 { 0x06, "Access failure" },
442 { 0x07, "Access congestion" },
443 { 0x08, "Subsystem failure" },
444 { 0x09, "Subsystem congestion" },
445 { 0x0a, "MTP failure" },
446 { 0x0b, "Network congestion" },
447 { 0x0c, "Expiration of reset timer" },
448 { 0x0d, "Expiration of receive inactivity timer" },
449 { 0x0e, "Reserved" },
450 { 0x0f, "Unqualified" },
451 { 0x10, "SCCP failure (ITU only)" },
455 #define RETURN_CAUSE_LENGTH 1
456 const value_string sccp_return_cause_values
[] = {
457 { 0x00, "No translation for an address of such nature" },
458 { 0x01, "No translation for this specific address" },
459 { 0x02, "Subsystem congestion" },
460 { 0x03, "Subsystem failure" },
461 { 0x04, "Unequipped failure" },
462 { 0x05, "MTP failure" },
463 { 0x06, "Network congestion" },
464 { 0x07, "Unqualified" },
465 { 0x08, "Error in message transport" },
466 { 0x09, "Error in local processing" },
467 { 0x0a, "Destination cannot perform reassembly" },
468 { 0x0b, "SCCP failure" },
469 { 0x0c, "Hop counter violation" },
470 { 0x0d, "Segmentation not supported" },
471 { 0x0e, "Segmentation failure" },
472 { 0xf7, "Message change failure (ANSI only)" },
473 { 0xf8, "Invalid INS routing request (ANSI only)" },
474 { 0xf9, "Invalid ISNI routing request (ANSI only)"},
475 { 0xfa, "Unauthorized message (ANSI only)" },
476 { 0xfb, "Message incompatibility (ANSI only)" },
477 { 0xfc, "Cannot perform ISNI constrained routing (ANSI only)" },
478 { 0xfd, "Redundant ISNI constrained routing (ANSI only)" },
479 { 0xfe, "Unable to perform ISNI identification (ANSI only)" },
483 #define RESET_CAUSE_LENGTH 1
484 const value_string sccp_reset_cause_values
[] = {
485 { 0x00, "End user originated" },
486 { 0x01, "SCCP user originated" },
487 { 0x02, "Message out of order - incorrect send sequence number" },
488 { 0x03, "Message out of order - incorrect receive sequence number" },
489 { 0x04, "Remote procedure error - message out of window" },
490 { 0x05, "Remote procedure error - incorrect send sequence number after (re)initialization" },
491 { 0x06, "Remote procedure error - general" },
492 { 0x07, "Remote end user operational" },
493 { 0x08, "Network operational" },
494 { 0x09, "Access operational" },
495 { 0x0a, "Network congestion" },
496 { 0x0b, "Reserved (ITU)/Not obtainable (ANSI)" },
497 { 0x0c, "Unqualified" },
501 #define ERROR_CAUSE_LENGTH 1
502 const value_string sccp_error_cause_values
[] = {
503 { 0x00, "Local Reference Number (LRN) mismatch - unassigned destination LRN" },
504 { 0x01, "Local Reference Number (LRN) mismatch - inconsistent source LRN" },
505 { 0x02, "Point code mismatch" },
506 { 0x03, "Service class mismatch" },
507 { 0x04, "Unqualified" },
511 #define REFUSAL_CAUSE_LENGTH 1
512 const value_string sccp_refusal_cause_values
[] = {
513 { 0x00, "End user originated" },
514 { 0x01, "End user congestion" },
515 { 0x02, "End user failure" },
516 { 0x03, "SCCP user originated" },
517 { 0x04, "Destination address unknown" },
518 { 0x05, "Destination inaccessible" },
519 { 0x06, "Network resource - QOS not available/non-transient" },
520 { 0x07, "Network resource - QOS not available/transient" },
521 { 0x08, "Access failure" },
522 { 0x09, "Access congestion" },
523 { 0x0a, "Subsystem failure" },
524 { 0x0b, "Subsystem congestion" },
525 { 0x0c, "Expiration of connection establishment timer" },
526 { 0x0d, "Incompatible user data" },
527 { 0x0e, "Reserved" },
528 { 0x0f, "Unqualified" },
529 { 0x10, "Hop counter violation" },
530 { 0x11, "SCCP failure (ITU only)" },
531 { 0x12, "No translation for an address of such nature" },
532 { 0x13, "Unequipped user" },
536 #define SEGMENTATION_LENGTH 4
537 #define SEGMENTATION_FIRST_SEGMENT_MASK 0x80
538 #define SEGMENTATION_CLASS_MASK 0x40
539 #define SEGMENTATION_SPARE_MASK 0x30
540 #define SEGMENTATION_REMAINING_MASK 0x0f
541 static const value_string sccp_segmentation_first_segment_values
[] = {
542 { 1, "First segment" },
543 { 0, "Not first segment" },
545 static const value_string sccp_segmentation_class_values
[] = {
546 { 0, "Class 0 selected" },
547 { 1, "Class 1 selected" },
551 #define HOP_COUNTER_LENGTH 1
553 #define IMPORTANCE_LENGTH 1
554 #define IMPORTANCE_IMPORTANCE_MASK 0x7
557 #define ANSI_ISNI_ROUTING_CONTROL_LENGTH 1
558 #define ANSI_ISNI_MI_MASK 0x01
559 #define ANSI_ISNI_IRI_MASK 0x06
560 #define ANSI_ISNI_RES_MASK 0x08
561 #define ANSI_ISNI_TI_MASK 0x10
562 #define ANSI_ISNI_TI_SHIFT 4
563 #define ANSI_ISNI_COUNTER_MASK 0xe0
564 #define ANSI_ISNI_NETSPEC_MASK 0x03
566 static const value_string sccp_isni_mark_for_id_values
[] = {
567 { 0x0, "Do not identify networks" },
568 { 0x1, "Identify networks" },
571 static const value_string sccp_isni_iri_values
[] = {
572 { 0x0, "Neither constrained nor suggested ISNI routing" },
573 { 0x1, "Constrained ISNI routing" },
574 { 0x2, "Reserved for suggested ISNI routing" },
578 #define ANSI_ISNI_TYPE_0 0x0
579 #define ANSI_ISNI_TYPE_1 0x1
580 static const value_string sccp_isni_ti_values
[] = {
581 { ANSI_ISNI_TYPE_0
, "Type zero ISNI parameter format" },
582 { ANSI_ISNI_TYPE_1
, "Type one ISNI parameter format" },
586 /* Initialize the protocol and registered fields */
587 static int proto_sccp
= -1;
588 static int hf_sccp_message_type
= -1;
589 static int hf_sccp_variable_pointer1
= -1;
590 static int hf_sccp_variable_pointer2
= -1;
591 static int hf_sccp_variable_pointer3
= -1;
592 static int hf_sccp_optional_pointer
= -1;
593 static int hf_sccp_param_length
= -1;
594 static int hf_sccp_ssn
= -1;
595 static int hf_sccp_gt_digits
= -1;
597 /* Called Party address */
598 static int hf_sccp_called_ansi_national_indicator
= -1;
599 static int hf_sccp_called_itu_natl_use_bit
= -1;
600 static int hf_sccp_called_routing_indicator
= -1;
601 static int hf_sccp_called_itu_global_title_indicator
= -1;
602 static int hf_sccp_called_ansi_global_title_indicator
= -1;
603 static int hf_sccp_called_itu_ssn_indicator
= -1;
604 static int hf_sccp_called_itu_point_code_indicator
= -1;
605 static int hf_sccp_called_ansi_ssn_indicator
= -1;
606 static int hf_sccp_called_ansi_point_code_indicator
= -1;
607 static int hf_sccp_called_ssn
= -1;
608 static int hf_sccp_called_pc_member
= -1;
609 static int hf_sccp_called_pc_cluster
= -1;
610 static int hf_sccp_called_pc_network
= -1;
611 static int hf_sccp_called_ansi_pc
= -1;
612 static int hf_sccp_called_chinese_pc
= -1;
613 static int hf_sccp_called_itu_pc
= -1;
614 static int hf_sccp_called_japan_pc
= -1;
615 static int hf_sccp_called_gt_nai
= -1;
616 static int hf_sccp_called_gt_oe
= -1;
617 static int hf_sccp_called_gt_tt
= -1;
618 static int hf_sccp_called_gt_np
= -1;
619 static int hf_sccp_called_gt_es
= -1;
620 static int hf_sccp_called_gt_digits
= -1;
621 static int hf_sccp_called_gt_digits_length
= -1;
623 /* Calling party address */
624 static int hf_sccp_calling_ansi_national_indicator
= -1;
625 static int hf_sccp_calling_itu_natl_use_bit
= -1;
626 static int hf_sccp_calling_routing_indicator
= -1;
627 static int hf_sccp_calling_itu_global_title_indicator
= -1;
628 static int hf_sccp_calling_ansi_global_title_indicator
= -1;
629 static int hf_sccp_calling_itu_ssn_indicator
= -1;
630 static int hf_sccp_calling_itu_point_code_indicator
= -1;
631 static int hf_sccp_calling_ansi_ssn_indicator
= -1;
632 static int hf_sccp_calling_ansi_point_code_indicator
= -1;
633 static int hf_sccp_calling_ssn
= -1;
634 static int hf_sccp_calling_pc_member
= -1;
635 static int hf_sccp_calling_pc_cluster
= -1;
636 static int hf_sccp_calling_pc_network
= -1;
637 static int hf_sccp_calling_ansi_pc
= -1;
638 static int hf_sccp_calling_chinese_pc
= -1;
639 static int hf_sccp_calling_itu_pc
= -1;
640 static int hf_sccp_calling_japan_pc
= -1;
641 static int hf_sccp_calling_gt_nai
= -1;
642 static int hf_sccp_calling_gt_oe
= -1;
643 static int hf_sccp_calling_gt_tt
= -1;
644 static int hf_sccp_calling_gt_np
= -1;
645 static int hf_sccp_calling_gt_es
= -1;
646 static int hf_sccp_calling_gt_digits
= -1;
647 static int hf_sccp_calling_gt_digits_length
= -1;
649 /* Other parameter values */
650 static int hf_sccp_dlr
= -1;
651 static int hf_sccp_slr
= -1;
652 static int hf_sccp_lr
= -1;
653 static int hf_sccp_class
= -1;
654 static int hf_sccp_handling
= -1;
655 static int hf_sccp_more
= -1;
656 static int hf_sccp_rsn
= -1;
657 static int hf_sccp_sequencing_segmenting_ssn
= -1;
658 static int hf_sccp_sequencing_segmenting_rsn
= -1;
659 static int hf_sccp_sequencing_segmenting_more
= -1;
660 static int hf_sccp_credit
= -1;
661 static int hf_sccp_release_cause
= -1;
662 static int hf_sccp_return_cause
= -1;
663 static int hf_sccp_reset_cause
= -1;
664 static int hf_sccp_error_cause
= -1;
665 static int hf_sccp_refusal_cause
= -1;
666 static int hf_sccp_segmentation_first
= -1;
667 static int hf_sccp_segmentation_class
= -1;
668 static int hf_sccp_segmentation_remaining
= -1;
669 static int hf_sccp_segmentation_slr
= -1;
670 static int hf_sccp_hop_counter
= -1;
671 static int hf_sccp_importance
= -1;
672 static int hf_sccp_ansi_isni_mi
= -1;
673 static int hf_sccp_ansi_isni_iri
= -1;
674 static int hf_sccp_ansi_isni_ti
= -1;
675 static int hf_sccp_ansi_isni_netspec
= -1;
676 static int hf_sccp_ansi_isni_counter
= -1;
677 static int hf_sccp_ansi_isni_network
= -1;
678 static int hf_sccp_ansi_isni_cluster
= -1;
679 static int hf_sccp_xudt_msg_fragments
= -1;
680 static int hf_sccp_xudt_msg_fragment
= -1;
681 static int hf_sccp_xudt_msg_fragment_overlap
= -1;
682 static int hf_sccp_xudt_msg_fragment_overlap_conflicts
= -1;
683 static int hf_sccp_xudt_msg_fragment_multiple_tails
= -1;
684 static int hf_sccp_xudt_msg_fragment_too_long_fragment
= -1;
685 static int hf_sccp_xudt_msg_fragment_error
= -1;
686 static int hf_sccp_xudt_msg_fragment_count
= -1;
687 static int hf_sccp_xudt_msg_reassembled_in
= -1;
688 static int hf_sccp_xudt_msg_reassembled_length
= -1;
689 static int hf_sccp_assoc_msg
= -1;
690 static int hf_sccp_assoc_id
= -1;
692 /* Initialize the subtree pointers */
693 static gint ett_sccp
= -1;
694 static gint ett_sccp_called
= -1;
695 static gint ett_sccp_called_ai
= -1;
696 static gint ett_sccp_called_pc
= -1;
697 static gint ett_sccp_called_gt
= -1;
698 static gint ett_sccp_called_gt_digits
= -1;
699 static gint ett_sccp_calling
= -1;
700 static gint ett_sccp_calling_ai
= -1;
701 static gint ett_sccp_calling_pc
= -1;
702 static gint ett_sccp_calling_gt
= -1;
703 static gint ett_sccp_calling_gt_digits
= -1;
704 static gint ett_sccp_sequencing_segmenting
= -1;
705 static gint ett_sccp_segmentation
= -1;
706 static gint ett_sccp_ansi_isni_routing_control
= -1;
707 static gint ett_sccp_xudt_msg_fragment
= -1;
708 static gint ett_sccp_xudt_msg_fragments
= -1;
709 static gint ett_sccp_assoc
= -1;
711 static expert_field ei_sccp_wrong_length
= EI_INIT
;
712 static expert_field ei_sccp_international_standard_address
= EI_INIT
;
713 static expert_field ei_sccp_no_ssn_present
= EI_INIT
;
714 static expert_field ei_sccp_ssn_zero
= EI_INIT
;
715 static expert_field ei_sccp_class_unexpected
= EI_INIT
;
716 static expert_field ei_sccp_handling_invalid
= EI_INIT
;
719 /* Declarations to desegment XUDT Messages */
720 static gboolean sccp_xudt_desegment
= TRUE
;
721 static gboolean show_key_params
= FALSE
;
722 static gboolean set_addresses
= FALSE
;
724 static int sccp_tap
= -1;
727 static const fragment_items sccp_xudt_msg_frag_items
= {
728 /* Fragment subtrees */
729 &ett_sccp_xudt_msg_fragment
,
730 &ett_sccp_xudt_msg_fragments
,
731 /* Fragment fields */
732 &hf_sccp_xudt_msg_fragments
,
733 &hf_sccp_xudt_msg_fragment
,
734 &hf_sccp_xudt_msg_fragment_overlap
,
735 &hf_sccp_xudt_msg_fragment_overlap_conflicts
,
736 &hf_sccp_xudt_msg_fragment_multiple_tails
,
737 &hf_sccp_xudt_msg_fragment_too_long_fragment
,
738 &hf_sccp_xudt_msg_fragment_error
,
739 &hf_sccp_xudt_msg_fragment_count
,
740 /* Reassembled in field */
741 &hf_sccp_xudt_msg_reassembled_in
,
742 /* Reassembled length field */
743 &hf_sccp_xudt_msg_reassembled_length
,
744 /* Reassembled data field */
747 "SCCP XUDT Message fragments"
750 static reassembly_table sccp_xudt_msg_reassembly_table
;
753 #define SCCP_USER_DATA 0
754 #define SCCP_USER_TCAP 1
755 #define SCCP_USER_RANAP 2
756 #define SCCP_USER_BSSAP 3
757 #define SCCP_USER_GSMMAP 4
758 #define SCCP_USER_CAMEL 5
759 #define SCCP_USER_INAP 6
761 typedef struct _sccp_user_t
{
767 dissector_handle_t
*handlep
;
770 static sccp_user_t
*sccp_users
;
771 static guint num_sccp_users
;
773 static dissector_handle_t data_handle
;
774 static dissector_handle_t tcap_handle
;
775 static dissector_handle_t ranap_handle
;
776 static dissector_handle_t bssap_handle
;
777 static dissector_handle_t gsmmap_handle
;
778 static dissector_handle_t camel_handle
;
779 static dissector_handle_t inap_handle
;
780 static dissector_handle_t default_handle
;
782 static const char *default_payload
= NULL
;
784 static const value_string sccp_users_vals
[] = {
785 { SCCP_USER_DATA
, "Data"},
786 { SCCP_USER_TCAP
, "TCAP"},
787 { SCCP_USER_RANAP
, "RANAP"},
788 { SCCP_USER_BSSAP
, "BSSAP"},
789 { SCCP_USER_GSMMAP
, "GSM MAP"},
790 { SCCP_USER_CAMEL
, "CAMEL"},
791 { SCCP_USER_INAP
, "INAP"},
796 * Here are the global variables associated with
797 * the various user definable characteristics of the dissection
799 static guint32 sccp_source_pc_global
= 0;
800 static gboolean sccp_show_length
= FALSE
;
802 static heur_dissector_list_t heur_subdissector_list
;
804 /* Keep track of SSN value of current message so if/when we get to the data
805 * parameter, we can call appropriate sub-dissector. TODO: can this info
806 * be stored elsewhere?
809 static guint8 message_type
= 0;
810 static guint dlr
= 0;
811 static guint slr
= 0;
813 static dissector_table_t sccp_ssn_dissector_table
;
815 static wmem_tree_t
*assocs
= NULL
;
816 static sccp_assoc_info_t
*assoc
;
817 static sccp_msg_info_t
*sccp_msg
;
818 static sccp_assoc_info_t no_assoc
= {0,0,0,0,0,FALSE
,FALSE
,NULL
,NULL
,SCCP_PLOAD_NONE
,NULL
,NULL
,NULL
,0};
819 static gboolean trace_sccp
= FALSE
;
820 static guint32 next_assoc_id
= 0;
822 static const value_string assoc_protos
[] = {
823 { SCCP_PLOAD_BSSAP
, "BSSAP" },
824 { SCCP_PLOAD_RANAP
, "RANAP" },
828 #define is_connectionless(m) \
829 ( m == SCCP_MSG_TYPE_UDT || m == SCCP_MSG_TYPE_UDTS \
830 || m == SCCP_MSG_TYPE_XUDT|| m == SCCP_MSG_TYPE_XUDTS \
831 || m == SCCP_MSG_TYPE_LUDT|| m == SCCP_MSG_TYPE_LUDTS)
833 #define RETURN_FALSE \
835 /*g_warning("Frame %d not protocol %d @ line %d", frame_num, my_mtp3_standard, __LINE__);*/ \
840 sccp_called_calling_looks_valid(guint32 frame_num _U_
, tvbuff_t
*tvb
, guint8 my_mtp3_standard
, gboolean is_co
)
842 guint8 ai
, ri
, gti
, ssni
, pci
;
843 guint8 len_needed
= 1; /* need at least the Address Indicator */
844 guint len
= tvb_length(tvb
);
846 ai
= tvb_get_guint8(tvb
, 0);
847 if ((my_mtp3_standard
== ANSI_STANDARD
) && ((ai
& ANSI_NATIONAL_MASK
) == 0))
850 gti
= (ai
& GTI_MASK
) >> GTI_SHIFT
;
851 if (my_mtp3_standard
== ANSI_STANDARD
) {
859 ri
= (ai
& ROUTING_INDICATOR_MASK
) >> ROUTING_INDICATOR_SHIFT
;
860 if (my_mtp3_standard
== ANSI_STANDARD
) {
861 pci
= ai
& ANSI_PC_INDICATOR_MASK
;
862 ssni
= ai
& ANSI_SSN_INDICATOR_MASK
;
864 ssni
= ai
& ITU_SSN_INDICATOR_MASK
;
865 pci
= ai
& ITU_PC_INDICATOR_MASK
;
868 /* Route on SSN with no SSN? */
869 if ((ri
== ROUTE_ON_SSN
) && (ssni
== 0))
872 /* Route on GT with no GT? */
873 if ((ri
== ROUTE_ON_GT
) && (gti
== AI_GTI_NO_GT
))
876 /* GT routed and connection-oriented (Class-2)?
877 * Yes, that's theoretically possible, but it's not used.
879 if ((ri
== ROUTE_ON_GT
) && is_co
)
883 len_needed
+= ADDRESS_SSN_LENGTH
;
885 if (my_mtp3_standard
== ANSI_STANDARD
||
886 my_mtp3_standard
== CHINESE_ITU_STANDARD
)
887 len_needed
+= ANSI_PC_LENGTH
;
889 len_needed
+= ITU_PC_LENGTH
;
894 if (len_needed
> len
)
901 looks_like_valid_sccp(guint32 frame_num _U_
, tvbuff_t
*tvb
, guint8 my_mtp3_standard
)
904 guint8 msgtype
, msg_class
, cause
;
905 guint called_ptr
= 0;
906 guint calling_ptr
= 0;
909 guint8 pointer_length
= POINTER_LENGTH
;
910 guint len
= tvb_length(tvb
);
912 /* Ensure we can do some basic checks without throwing an exception.
913 * Accesses beyond this length need to check the length first because
914 * we don't want to throw an exception in here...
919 msgtype
= tvb_get_guint8(tvb
, SCCP_MSG_TYPE_OFFSET
);
920 if (!try_val_to_str(msgtype
, sccp_message_type_acro_values
)) {
923 offset
= SCCP_MSG_TYPE_LENGTH
;
926 case SCCP_MSG_TYPE_UDT
:
927 case SCCP_MSG_TYPE_XUDT
:
928 case SCCP_MSG_TYPE_LUDT
:
929 case SCCP_MSG_TYPE_UDTS
:
930 case SCCP_MSG_TYPE_XUDTS
:
931 case SCCP_MSG_TYPE_LUDTS
:
933 if (msgtype
== SCCP_MSG_TYPE_XUDT
|| msgtype
== SCCP_MSG_TYPE_XUDTS
) {
934 if (SCCP_MSG_TYPE_LENGTH
+
935 PROTOCOL_CLASS_LENGTH
+ /* or Cause for XUDTS */
940 POINTER_LENGTH
> len
)
944 if (msgtype
== SCCP_MSG_TYPE_LUDT
|| msgtype
== SCCP_MSG_TYPE_LUDTS
) {
945 if (SCCP_MSG_TYPE_LENGTH
+
946 PROTOCOL_CLASS_LENGTH
+ /* or Cause for LUDTS */
948 POINTER_LENGTH_LONG
+
949 POINTER_LENGTH_LONG
+
950 POINTER_LENGTH_LONG
+
951 POINTER_LENGTH_LONG
> len
)
954 pointer_length
= POINTER_LENGTH_LONG
;
957 if (msgtype
== SCCP_MSG_TYPE_UDT
|| msgtype
== SCCP_MSG_TYPE_XUDT
||
958 msgtype
== SCCP_MSG_TYPE_LUDT
) {
960 msg_class
= tvb_get_guint8(tvb
, offset
) & CLASS_CLASS_MASK
;
963 offset
+= PROTOCOL_CLASS_LENGTH
;
966 if (msgtype
== SCCP_MSG_TYPE_XUDT
|| msgtype
== SCCP_MSG_TYPE_LUDT
)
967 offset
+= HOP_COUNTER_LENGTH
;
969 if (msgtype
== SCCP_MSG_TYPE_UDTS
||
970 msgtype
== SCCP_MSG_TYPE_XUDTS
||
971 msgtype
== SCCP_MSG_TYPE_LUDTS
) {
973 cause
= tvb_get_guint8(tvb
, offset
);
974 if (!try_val_to_str(cause
, sccp_return_cause_values
))
976 offset
+= RETURN_CAUSE_LENGTH
;
979 if (msgtype
== SCCP_MSG_TYPE_XUDTS
|| msgtype
== SCCP_MSG_TYPE_LUDTS
)
980 offset
+= HOP_COUNTER_LENGTH
;
982 if (msgtype
== SCCP_MSG_TYPE_LUDT
|| msgtype
== SCCP_MSG_TYPE_LUDTS
)
983 called_ptr
= tvb_get_letohs(tvb
, offset
);
985 called_ptr
= tvb_get_guint8(tvb
, offset
);
986 if (called_ptr
== 0) /* Mandatory variable parameters must be present */
988 called_ptr
+= offset
;
989 offset
+= pointer_length
;
991 if (msgtype
== SCCP_MSG_TYPE_LUDT
|| msgtype
== SCCP_MSG_TYPE_LUDTS
)
992 calling_ptr
= tvb_get_letohs(tvb
, offset
);
994 calling_ptr
= tvb_get_guint8(tvb
, offset
);
995 if (calling_ptr
== 0) /* Mandatory variable parameters must be present */
997 calling_ptr
+= offset
;
998 offset
+= pointer_length
;
1000 if (msgtype
== SCCP_MSG_TYPE_LUDT
|| msgtype
== SCCP_MSG_TYPE_LUDTS
)
1001 data_ptr
= tvb_get_letohs(tvb
, offset
);
1003 data_ptr
= tvb_get_guint8(tvb
, offset
);
1004 if (data_ptr
== 0) /* Mandatory variable parameters must be present */
1007 offset
+= pointer_length
;
1009 if (msgtype
== SCCP_MSG_TYPE_XUDT
|| msgtype
== SCCP_MSG_TYPE_XUDTS
) {
1010 opt_ptr
= tvb_get_guint8(tvb
, offset
);
1011 offset
+= POINTER_LENGTH
;
1012 } else if (msgtype
== SCCP_MSG_TYPE_LUDT
|| msgtype
== SCCP_MSG_TYPE_LUDTS
) {
1013 opt_ptr
= tvb_get_letohs(tvb
, offset
);
1014 offset
+= POINTER_LENGTH_LONG
;
1017 if (msgtype
== SCCP_MSG_TYPE_LUDT
|| msgtype
== SCCP_MSG_TYPE_LUDTS
) {
1018 /* Long pointers count from the 2nd (MSB) octet of the pointer */
1026 /* Check that the variable pointers are within bounds */
1027 if (called_ptr
> len
|| calling_ptr
> len
|| data_ptr
> len
)
1030 /* Check that the lengths of the variable parameters are within bounds */
1031 if (tvb_get_guint8(tvb
, called_ptr
)+called_ptr
> len
||
1032 tvb_get_guint8(tvb
, calling_ptr
)+calling_ptr
> len
)
1034 if (msgtype
== SCCP_MSG_TYPE_LUDT
|| msgtype
== SCCP_MSG_TYPE_LUDTS
) {
1035 if (tvb_get_letohs(tvb
, data_ptr
)+data_ptr
> len
)
1038 if (tvb_get_guint8(tvb
, data_ptr
)+data_ptr
> len
)
1043 case SCCP_MSG_TYPE_CR
:
1045 if (len
< SCCP_MSG_TYPE_LENGTH
1046 + DESTINATION_LOCAL_REFERENCE_LENGTH
1047 + PROTOCOL_CLASS_LENGTH
1052 offset
+= DESTINATION_LOCAL_REFERENCE_LENGTH
;
1054 /* Class is only the lower 4 bits, but the upper 4 bits are spare
1055 * in Class-2. Don't mask them off so the below comparison also
1056 * fails if any of those spare bits are set.
1058 msg_class
= tvb_get_guint8(tvb
, offset
);
1062 offset
+= PROTOCOL_CLASS_LENGTH
;
1063 data_ptr
= tvb_get_guint8(tvb
, offset
);
1067 offset
+= POINTER_LENGTH
;
1068 opt_ptr
= tvb_get_guint8(tvb
, offset
);
1072 offset
+= POINTER_LENGTH
;
1075 case SCCP_MSG_TYPE_CC
:
1077 if (len
< SCCP_MSG_TYPE_LENGTH
1078 + DESTINATION_LOCAL_REFERENCE_LENGTH
1079 + SOURCE_LOCAL_REFERENCE_LENGTH
1080 + PROTOCOL_CLASS_LENGTH
1084 offset
+= DESTINATION_LOCAL_REFERENCE_LENGTH
;
1085 offset
+= SOURCE_LOCAL_REFERENCE_LENGTH
;
1087 /* Class is only the lower 4 bits, but the upper 4 bits are spare
1088 * in Class-2. Don't mask them off so the below comparison also
1089 * fails if any of those spare bits are set.
1091 msg_class
= tvb_get_guint8(tvb
, offset
);
1094 offset
+= PROTOCOL_CLASS_LENGTH
;
1096 opt_ptr
= tvb_get_guint8(tvb
, offset
);
1097 offset
+= POINTER_LENGTH
;
1099 /* If the pointer isn't 0 (no optional parameters) or 1 (optional
1100 * parameter starts immediately after the pointer) then what would
1101 * be between the pointer and the parameter?
1106 /* If there are no optional parameters, are we at the end of the
1109 if ((opt_ptr
== 0) && (offset
!= len
))
1113 case SCCP_MSG_TYPE_CREF
:
1115 if (len
< SCCP_MSG_TYPE_LENGTH
1116 + DESTINATION_LOCAL_REFERENCE_LENGTH
1117 + REFUSAL_CAUSE_LENGTH
1121 offset
+= DESTINATION_LOCAL_REFERENCE_LENGTH
;
1123 cause
= tvb_get_guint8(tvb
, offset
);
1124 if (!try_val_to_str(cause
, sccp_refusal_cause_values
))
1126 offset
+= REFUSAL_CAUSE_LENGTH
;
1128 opt_ptr
= tvb_get_guint8(tvb
, offset
);
1129 offset
+= POINTER_LENGTH
;
1131 /* If the pointer isn't 0 (no optional parameters) or 1 (optional
1132 * parameter starts immediately after the pointer) then what would
1133 * be between the pointer and the parameter?
1138 /* If there are no optional parameters, are we at the end of the
1141 if ((opt_ptr
== 0) && (offset
!= len
))
1145 case SCCP_MSG_TYPE_RLSD
:
1147 if (len
< SCCP_MSG_TYPE_LENGTH
1148 + DESTINATION_LOCAL_REFERENCE_LENGTH
1149 + SOURCE_LOCAL_REFERENCE_LENGTH
1150 + RELEASE_CAUSE_LENGTH
1154 offset
+= DESTINATION_LOCAL_REFERENCE_LENGTH
;
1155 offset
+= SOURCE_LOCAL_REFERENCE_LENGTH
;
1157 cause
= tvb_get_guint8(tvb
, offset
);
1158 if (!try_val_to_str(cause
, sccp_release_cause_values
))
1160 offset
+= RELEASE_CAUSE_LENGTH
;
1162 opt_ptr
= tvb_get_guint8(tvb
, offset
);
1163 offset
+= POINTER_LENGTH
;
1165 /* If the pointer isn't 0 (no optional parameters) or 1 (optional
1166 * parameter starts immediately after the pointer) then what would
1167 * be between the pointer and the parameter?
1172 /* If there are no optional parameters, are we at the end of the
1175 if ((opt_ptr
== 0) && (offset
!= len
))
1179 case SCCP_MSG_TYPE_RLC
:
1181 if (len
!= SCCP_MSG_TYPE_LENGTH
1182 + DESTINATION_LOCAL_REFERENCE_LENGTH
1183 + SOURCE_LOCAL_REFERENCE_LENGTH
)
1187 case SCCP_MSG_TYPE_ERR
:
1189 if (len
!= SCCP_MSG_TYPE_LENGTH
1190 + DESTINATION_LOCAL_REFERENCE_LENGTH
1191 + ERROR_CAUSE_LENGTH
)
1194 offset
+= DESTINATION_LOCAL_REFERENCE_LENGTH
;
1196 cause
= tvb_get_guint8(tvb
, offset
);
1197 if (!try_val_to_str(cause
, sccp_error_cause_values
))
1201 case SCCP_MSG_TYPE_DT1
:
1203 if (len
< SCCP_MSG_TYPE_LENGTH
1204 + DESTINATION_LOCAL_REFERENCE_LENGTH
1205 + SEGMENTING_REASSEMBLING_LENGTH
1207 + PARAMETER_LENGTH_LENGTH
1208 + 1) /* At least 1 byte of payload */
1210 offset
+= DESTINATION_LOCAL_REFERENCE_LENGTH
;
1212 /* Are any of the spare bits in set? */
1213 if (tvb_get_guint8(tvb
, offset
) & ~SEGMENTING_REASSEMBLING_MASK
)
1215 offset
+= SEGMENTING_REASSEMBLING_LENGTH
;
1217 data_ptr
= tvb_get_guint8(tvb
, offset
) + offset
;
1218 /* Verify the data pointer is within bounds */
1221 offset
+= POINTER_LENGTH
;
1223 /* Verify the data length uses the rest of the message */
1224 if (tvb_get_guint8(tvb
, data_ptr
) + offset
+ 1U != len
)
1228 case SCCP_MSG_TYPE_IT
:
1230 if (len
< SCCP_MSG_TYPE_LENGTH
1231 + DESTINATION_LOCAL_REFERENCE_LENGTH
1232 + SOURCE_LOCAL_REFERENCE_LENGTH
1233 + PROTOCOL_CLASS_LENGTH
1234 + SEQUENCING_SEGMENTING_LENGTH
1238 offset
+= DESTINATION_LOCAL_REFERENCE_LENGTH
;
1239 offset
+= SOURCE_LOCAL_REFERENCE_LENGTH
;
1241 /* Class is only the lower 4 bits, but the upper 4 bits are spare
1242 * in Class-2. Don't mask them off so the below comparison also
1243 * fails if any of those spare bits are set.
1245 msg_class
= tvb_get_guint8(tvb
, offset
);
1248 offset
+= PROTOCOL_CLASS_LENGTH
;
1251 case SCCP_MSG_TYPE_AK
:
1252 case SCCP_MSG_TYPE_DT2
:
1253 case SCCP_MSG_TYPE_EA
:
1254 case SCCP_MSG_TYPE_ED
:
1255 case SCCP_MSG_TYPE_RSC
:
1256 case SCCP_MSG_TYPE_RSR
:
1257 /* Class-3 is never actually used in the real world */
1262 DISSECTOR_ASSERT_NOT_REACHED();
1266 guint8 param_len
= tvb_get_guint8(tvb
, called_ptr
);
1267 tvbuff_t
*param_tvb
;
1271 param_tvb
= tvb_new_subset(tvb
, called_ptr
+1, param_len
, param_len
);
1273 if (!sccp_called_calling_looks_valid(frame_num
, param_tvb
, my_mtp3_standard
, !is_connectionless(msgtype
)))
1278 guint8 param_len
= tvb_get_guint8(tvb
, calling_ptr
);
1279 tvbuff_t
*param_tvb
;
1283 param_tvb
= tvb_new_subset(tvb
, calling_ptr
+1, param_len
, param_len
);
1285 if (!sccp_called_calling_looks_valid(frame_num
, param_tvb
, my_mtp3_standard
, !is_connectionless(msgtype
)))
1292 opt_ptr
+= offset
-pointer_length
; /* (offset was already incremented) */
1294 /* Check that the optional pointer is within bounds */
1298 opt_param
= tvb_get_guint8(tvb
, opt_ptr
);
1299 /* Check if the (1st) optional parameter tag is valid */
1300 if (!try_val_to_str(opt_param
, sccp_parameter_values
))
1303 /* Check that the (1st) parameter length is within bounds */
1304 if ((opt_param
!= PARAMETER_END_OF_OPTIONAL_PARAMETERS
) &&
1305 ((opt_ptr
+1U) <= len
) &&
1306 ((tvb_get_guint8(tvb
, opt_ptr
+1U)+offset
) > len
))
1309 /* If we're at the end of the parameters, are we also at the end of the
1312 if ((opt_param
== PARAMETER_END_OF_OPTIONAL_PARAMETERS
) && ((opt_ptr
+1U) != len
))
1319 static sccp_assoc_info_t
*
1320 new_assoc(guint32 calling
, guint32 called
)
1322 sccp_assoc_info_t
*a
= wmem_new0(wmem_file_scope(), sccp_assoc_info_t
);
1324 a
->id
= next_assoc_id
++;
1325 a
->calling_dpc
= calling
;
1326 a
->called_dpc
= called
;
1327 a
->calling_ssn
= INVALID_SSN
;
1328 a
->called_ssn
= INVALID_SSN
;
1331 a
->payload
= SCCP_PLOAD_NONE
;
1332 a
->calling_party
= NULL
;
1333 a
->called_party
= NULL
;
1334 a
->extra_info
= NULL
;
1340 reset_sccp_assoc(void)
1346 get_sccp_assoc(packet_info
*pinfo
, guint offset
, guint32 src_lr
, guint32 dst_lr
, guint msg_type
)
1349 address
*opc
= &(pinfo
->src
);
1350 address
*dpc
= &(pinfo
->dst
);
1351 guint framenum
= PINFO_FD_NUM(pinfo
);
1356 opck
= opc
->type
== AT_SS7PC
? mtp3_pc_hash((const mtp3_addr_pc_t
*)opc
->data
) : g_str_hash(ep_address_to_str(opc
));
1357 dpck
= dpc
->type
== AT_SS7PC
? mtp3_pc_hash((const mtp3_addr_pc_t
*)dpc
->data
) : g_str_hash(ep_address_to_str(dpc
));
1361 case SCCP_MSG_TYPE_CR
:
1363 /* CR contains the opc,dpc,dlr key of backward messages swapped as dpc,opc,slr */
1364 wmem_tree_key_t bw_key
[] = {
1371 if (! ( assoc
= (sccp_assoc_info_t
*)wmem_tree_lookup32_array(assocs
, bw_key
) ) && ! PINFO_FD_VISITED(pinfo
) ) {
1372 assoc
= new_assoc(opck
, dpck
);
1373 wmem_tree_insert32_array(assocs
, bw_key
, assoc
);
1374 assoc
->has_bw_key
= TRUE
;
1377 pinfo
->p2p_dir
= P2P_DIR_SENT
;
1381 case SCCP_MSG_TYPE_CC
:
1383 wmem_tree_key_t fw_key
[] = {
1384 {1, &dpck
}, {1, &opck
}, {1, &src_lr
}, {0, NULL
}
1386 wmem_tree_key_t bw_key
[] = {
1387 {1, &opck
}, {1, &dpck
}, {1, &dst_lr
}, {0, NULL
}
1390 if ( ( assoc
= (sccp_assoc_info_t
*)wmem_tree_lookup32_array(assocs
, bw_key
) ) ) {
1394 if ( (assoc
= (sccp_assoc_info_t
*)wmem_tree_lookup32_array(assocs
, fw_key
) ) ) {
1398 assoc
= new_assoc(dpck
, opck
);
1402 pinfo
->p2p_dir
= P2P_DIR_RECV
;
1404 if ( ! PINFO_FD_VISITED(pinfo
) && ! assoc
->has_bw_key
) {
1405 wmem_tree_insert32_array(assocs
, bw_key
, assoc
);
1406 assoc
->has_bw_key
= TRUE
;
1409 if ( ! PINFO_FD_VISITED(pinfo
) && ! assoc
->has_fw_key
) {
1410 wmem_tree_insert32_array(assocs
, fw_key
, assoc
);
1411 assoc
->has_fw_key
= TRUE
;
1416 case SCCP_MSG_TYPE_RLC
:
1418 wmem_tree_key_t bw_key
[] = {
1419 {1, &dpck
}, {1, &opck
}, {1, &src_lr
}, {0, NULL
}
1421 wmem_tree_key_t fw_key
[] = {
1422 {1, &opck
}, {1, &dpck
}, {1, &dst_lr
}, {0, NULL
}
1424 if ( ( assoc
= (sccp_assoc_info_t
*)wmem_tree_lookup32_array(assocs
, bw_key
) ) ) {
1428 if ( (assoc
= (sccp_assoc_info_t
*)wmem_tree_lookup32_array(assocs
, fw_key
) ) ) {
1432 assoc
= new_assoc(dpck
, opck
);
1436 pinfo
->p2p_dir
= P2P_DIR_SENT
;
1438 if ( ! PINFO_FD_VISITED(pinfo
) && ! assoc
->has_bw_key
) {
1439 wmem_tree_insert32_array(assocs
, bw_key
, assoc
);
1440 assoc
->has_bw_key
= TRUE
;
1443 if ( ! PINFO_FD_VISITED(pinfo
) && ! assoc
->has_fw_key
) {
1444 wmem_tree_insert32_array(assocs
, fw_key
, assoc
);
1445 assoc
->has_fw_key
= TRUE
;
1451 wmem_tree_key_t key
[] = {
1452 {1, &opck
}, {1, &dpck
}, {1, &dst_lr
}, {0, NULL
}
1455 assoc
= (sccp_assoc_info_t
*)wmem_tree_lookup32_array(assocs
, key
);
1458 if (assoc
->calling_dpc
== dpck
) {
1459 pinfo
->p2p_dir
= P2P_DIR_RECV
;
1461 pinfo
->p2p_dir
= P2P_DIR_SENT
;
1469 if (assoc
&& trace_sccp
) {
1470 if ( ! PINFO_FD_VISITED(pinfo
)) {
1471 sccp_msg_info_t
*msg
= wmem_new0(wmem_file_scope(), sccp_msg_info_t
);
1472 msg
->framenum
= framenum
;
1473 msg
->offset
= offset
;
1474 msg
->data
.co
.next
= NULL
;
1475 msg
->data
.co
.assoc
= assoc
;
1476 msg
->data
.co
.label
= NULL
;
1477 msg
->data
.co
.comment
= NULL
;
1478 msg
->type
= msg_type
;
1482 for (m
= assoc
->msgs
; m
->data
.co
.next
; m
= m
->data
.co
.next
) ;
1483 m
->data
.co
.next
= msg
;
1488 assoc
->curr_msg
= msg
;
1494 for (m
= assoc
->msgs
; m
; m
= m
->data
.co
.next
) {
1495 if ((m
->framenum
== framenum
) && (m
->offset
== offset
)) {
1496 assoc
->curr_msg
= m
;
1503 return assoc
? assoc
: &no_assoc
;
1508 dissect_sccp_unknown_message(tvbuff_t
*message_tvb
, proto_tree
*sccp_tree
)
1510 guint32 message_length
;
1512 message_length
= tvb_length(message_tvb
);
1514 proto_tree_add_text(sccp_tree
, message_tvb
, 0, message_length
,
1515 "Unknown message (%u byte%s)",
1516 message_length
, plurality(message_length
, "", "s"));
1520 dissect_sccp_unknown_param(tvbuff_t
*tvb
, proto_tree
*tree
, guint8 type
, guint length
)
1522 proto_tree_add_text(tree
, tvb
, 0, length
, "Unknown parameter 0x%x (%u byte%s)",
1523 type
, length
, plurality(length
, "", "s"));
1527 dissect_sccp_dlr_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
1529 proto_item
*lr_item
;
1532 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
1533 "Wrong length indicated. Expected 3, got %u", length
);
1537 dlr
= tvb_get_letoh24(tvb
, 0);
1538 proto_tree_add_uint(tree
, hf_sccp_dlr
, tvb
, 0, length
, dlr
);
1539 lr_item
= proto_tree_add_uint(tree
, hf_sccp_lr
, tvb
, 0, length
, dlr
);
1540 PROTO_ITEM_SET_HIDDEN(lr_item
);
1542 if (show_key_params
)
1543 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "DLR=%d ", dlr
);
1547 dissect_sccp_slr_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
1549 proto_item
*lr_item
;
1552 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
1553 "Wrong length indicated. Expected 3, got %u", length
);
1557 slr
= tvb_get_letoh24(tvb
, 0);
1558 proto_tree_add_uint(tree
, hf_sccp_slr
, tvb
, 0, length
, slr
);
1559 lr_item
= proto_tree_add_uint(tree
, hf_sccp_lr
, tvb
, 0, length
, slr
);
1560 PROTO_ITEM_SET_HIDDEN(lr_item
);
1562 if (show_key_params
)
1563 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "SLR=%d ", slr
);
1567 dissect_sccp_gt_address_information(tvbuff_t
*tvb
, packet_info
*pinfo
,
1568 proto_tree
*tree
, guint length
,
1569 gboolean even_length
, gboolean called
,
1570 gboolean route_on_gt
)
1573 guint8 odd_signal
, even_signal
;
1574 proto_item
*digits_item
;
1575 proto_tree
*digits_tree
;
1578 gt_digits
= (char *)wmem_alloc0(wmem_packet_scope(), GT_MAX_SIGNALS
+1);
1580 while (offset
< length
) {
1581 odd_signal
= tvb_get_guint8(tvb
, offset
) & GT_ODD_SIGNAL_MASK
;
1582 even_signal
= tvb_get_guint8(tvb
, offset
) & GT_EVEN_SIGNAL_MASK
;
1583 even_signal
>>= GT_EVEN_SIGNAL_SHIFT
;
1585 g_strlcat(gt_digits
, val_to_str(odd_signal
, sccp_address_signal_values
,
1586 "Unknown: %d"), GT_MAX_SIGNALS
+1);
1588 /* If the last signal is NOT filler */
1589 if (offset
!= (length
- 1) || even_length
== TRUE
)
1590 g_strlcat(gt_digits
, val_to_str(even_signal
, sccp_address_signal_values
,
1591 "Unknown: %d"), GT_MAX_SIGNALS
+1);
1593 offset
+= GT_SIGNAL_LENGTH
;
1596 if (is_connectionless(message_type
) && sccp_msg
) {
1597 guint8
**gt_ptr
= called
? &(sccp_msg
->data
.ud
.called_gt
) : &(sccp_msg
->data
.ud
.calling_gt
);
1599 *gt_ptr
= (guint8
*)wmem_strdup(wmem_packet_scope(), gt_digits
);
1602 digits_item
= proto_tree_add_string(tree
, called
? hf_sccp_called_gt_digits
1603 : hf_sccp_calling_gt_digits
,
1604 tvb
, 0, length
, gt_digits
);
1605 digits_tree
= proto_item_add_subtree(digits_item
, called
? ett_sccp_called_gt_digits
1606 : ett_sccp_calling_gt_digits
);
1608 if (set_addresses
&& route_on_gt
) {
1610 SET_ADDRESS(&pinfo
->dst
, AT_STRINGZ
, 1+(int)strlen(gt_digits
), gt_digits
);
1612 SET_ADDRESS(&pinfo
->src
, AT_STRINGZ
, 1+(int)strlen(gt_digits
), gt_digits
);
1616 proto_tree_add_string(digits_tree
, hf_sccp_gt_digits
, tvb
, 0, length
, gt_digits
);
1617 proto_tree_add_uint(digits_tree
, called
? hf_sccp_called_gt_digits_length
1618 : hf_sccp_calling_gt_digits_length
,
1619 tvb
, 0, length
, (guint32
)strlen(gt_digits
));
1625 dissect_sccp_global_title(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
,
1626 guint8 gti
, gboolean route_on_gt
, gboolean called
)
1628 proto_item
*gt_item
;
1629 proto_tree
*gt_tree
;
1630 proto_tree
*digits_tree
;
1631 tvbuff_t
*signals_tvb
;
1633 guint8 odd_even
, nai
= 0, np
= 0, es
;
1634 gboolean even
= TRUE
;
1636 /* Shift GTI to where we can work with it */
1639 gt_item
= proto_tree_add_text(tree
, tvb
, offset
, length
,
1640 "Global Title 0x%x (%u byte%s)",
1641 gti
, length
, plurality(length
,"", "s"));
1642 gt_tree
= proto_item_add_subtree(gt_item
, called
? ett_sccp_called_gt
1643 : ett_sccp_calling_gt
);
1645 /* Decode Transation Type (if present) */
1646 if ((gti
== AI_GTI_TT
) ||
1647 ((decode_mtp3_standard
!= ANSI_STANDARD
) &&
1648 ((gti
== ITU_AI_GTI_TT_NP_ES
) || (gti
== ITU_AI_GTI_TT_NP_ES_NAI
))) ||
1649 ((decode_mtp3_standard
== ANSI_STANDARD
) && (gti
== ANSI_AI_GTI_TT_NP_ES
))) {
1651 proto_tree_add_item(gt_tree
, called
? hf_sccp_called_gt_tt
1652 : hf_sccp_calling_gt_tt
,
1653 tvb
, offset
, GT_TT_LENGTH
, ENC_NA
);
1654 offset
+= GT_TT_LENGTH
;
1657 if (gti
== AI_GTI_TT
) {
1658 /* Protocol doesn't tell us, so we ASSUME even... */
1662 /* Decode Numbering Plan and Encoding Scheme (if present) */
1663 if (((decode_mtp3_standard
!= ANSI_STANDARD
) &&
1664 ((gti
== ITU_AI_GTI_TT_NP_ES
) || (gti
== ITU_AI_GTI_TT_NP_ES_NAI
))) ||
1665 ((decode_mtp3_standard
== ANSI_STANDARD
) && (gti
== ANSI_AI_GTI_TT_NP_ES
))) {
1667 np
= tvb_get_guint8(tvb
, offset
) & GT_NP_MASK
;
1668 proto_tree_add_uint(gt_tree
, called
? hf_sccp_called_gt_np
1669 : hf_sccp_calling_gt_np
,
1670 tvb
, offset
, GT_NP_ES_LENGTH
, np
);
1672 es
= tvb_get_guint8(tvb
, offset
) & GT_ES_MASK
;
1673 proto_tree_add_uint(gt_tree
, called
? hf_sccp_called_gt_es
1674 : hf_sccp_calling_gt_es
,
1675 tvb
, offset
, GT_NP_ES_LENGTH
, es
);
1677 even
= (es
== GT_ES_BCD_EVEN
) ? TRUE
: FALSE
;
1679 offset
+= GT_NP_ES_LENGTH
;
1682 /* Decode Nature of Address Indicator (if present) */
1683 if ((decode_mtp3_standard
!= ANSI_STANDARD
) &&
1684 ((gti
== ITU_AI_GTI_NAI
) || (gti
== ITU_AI_GTI_TT_NP_ES_NAI
))) {
1686 /* Decode Odd/Even Indicator (if present) */
1687 if (gti
== ITU_AI_GTI_NAI
) {
1688 odd_even
= tvb_get_guint8(tvb
, offset
) & GT_OE_MASK
;
1689 proto_tree_add_uint(gt_tree
, called
? hf_sccp_called_gt_oe
1690 : hf_sccp_calling_gt_oe
,
1691 tvb
, offset
, GT_NAI_LENGTH
, odd_even
);
1692 even
= (odd_even
== GT_OE_EVEN
) ? TRUE
: FALSE
;
1695 nai
= tvb_get_guint8(tvb
, offset
) & GT_NAI_MASK
;
1696 proto_tree_add_uint(gt_tree
, called
? hf_sccp_called_gt_nai
1697 : hf_sccp_calling_gt_nai
,
1698 tvb
, offset
, GT_NAI_LENGTH
, nai
);
1700 offset
+= GT_NAI_LENGTH
;
1703 /* Decode address signal(s) */
1704 if (length
< offset
)
1707 signals_tvb
= tvb_new_subset(tvb
, offset
, (length
- offset
),
1710 digits_tree
= dissect_sccp_gt_address_information(signals_tvb
, pinfo
, gt_tree
,
1712 even
, called
, route_on_gt
);
1714 /* Display the country code (if we can) */
1715 switch (np
>> GT_NP_SHIFT
) {
1717 case GT_NP_ISDN_MOBILE
:
1718 if (nai
== GT_NAI_INTERNATIONAL_NUM
) {
1719 dissect_e164_cc(signals_tvb
, digits_tree
, 0, TRUE
);
1722 case GT_NP_LAND_MOBILE
:
1723 dissect_e212_mcc_mnc_in_address(signals_tvb
, pinfo
, digits_tree
, 0);
1731 dissect_sccp_3byte_pc(tvbuff_t
*tvb
, proto_tree
*call_tree
, guint offset
,
1736 if (decode_mtp3_standard
== ANSI_STANDARD
)
1739 hf_pc
= hf_sccp_called_ansi_pc
;
1741 hf_pc
= hf_sccp_calling_ansi_pc
;
1742 } else /* CHINESE_ITU_STANDARD */ {
1744 hf_pc
= hf_sccp_called_chinese_pc
;
1746 hf_pc
= hf_sccp_calling_chinese_pc
;
1749 /* create and fill the PC tree */
1750 dissect_mtp3_3byte_pc(tvb
, offset
, call_tree
,
1751 called
? ett_sccp_called_pc
: ett_sccp_calling_pc
,
1753 called
? hf_sccp_called_pc_network
: hf_sccp_calling_pc_network
,
1754 called
? hf_sccp_called_pc_cluster
: hf_sccp_calling_pc_cluster
,
1755 called
? hf_sccp_called_pc_member
: hf_sccp_calling_pc_member
,
1758 return(offset
+ ANSI_PC_LENGTH
);
1761 /* FUNCTION dissect_sccp_called_calling_param():
1762 * Dissect the Calling or Called Party Address parameters.
1764 * The boolean 'called' describes whether this function is decoding a
1765 * called (TRUE) or calling (FALSE) party address. There is simply too
1766 * much code in this function to have 2 copies of it (one for called, one
1769 * NOTE: this function is called even when (!tree) so that we can get
1770 * the SSN and subsequently call subdissectors (if and when there's a data
1771 * parameter). Realistically we should put if (!tree)'s around a lot of the
1772 * code, but I think that would make it unreadable--and the expense of not
1773 * doing so does not appear to be very high.
1776 dissect_sccp_called_calling_param(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
,
1777 guint length
, gboolean called
)
1779 proto_item
*call_item
= 0, *call_ai_item
= 0, *item
, *hidden_item
, *expert_item
;
1780 proto_tree
*call_tree
= 0, *call_ai_tree
= 0;
1782 guint8 national
= 0xFFU
, routing_ind
, gti
, pci
, ssni
, ssn
;
1784 dissector_handle_t ssn_dissector
= NULL
, tcap_ssn_dissector
= NULL
;
1785 const char *ssn_dissector_short_name
= NULL
;
1786 const char *tcap_ssn_dissector_short_name
= NULL
;
1788 call_item
= proto_tree_add_text(tree
, tvb
, 0, length
,
1789 "%s Party address (%u byte%s)",
1790 called
? "Called" : "Calling", length
,
1791 plurality(length
, "", "s"));
1792 call_tree
= proto_item_add_subtree(call_item
, called
? ett_sccp_called
: ett_sccp_calling
);
1794 call_ai_item
= proto_tree_add_text(call_tree
, tvb
, 0,
1795 ADDRESS_INDICATOR_LENGTH
,
1796 "Address Indicator");
1797 call_ai_tree
= proto_item_add_subtree(call_ai_item
, called
? ett_sccp_called_ai
: ett_sccp_calling_ai
);
1799 if (decode_mtp3_standard
== ANSI_STANDARD
) {
1800 national
= tvb_get_guint8(tvb
, 0) & ANSI_NATIONAL_MASK
;
1801 expert_item
= proto_tree_add_uint(call_ai_tree
, called
? hf_sccp_called_ansi_national_indicator
1802 : hf_sccp_calling_ansi_national_indicator
,
1803 tvb
, 0, ADDRESS_INDICATOR_LENGTH
, national
);
1805 expert_add_info(pinfo
, expert_item
, &ei_sccp_international_standard_address
);
1807 guint8 natl_use_bit
= tvb_get_guint8(tvb
, 0) & ITU_RESERVED_MASK
;
1809 proto_tree_add_uint(call_ai_tree
, called
? hf_sccp_called_itu_natl_use_bit
1810 : hf_sccp_calling_itu_natl_use_bit
,
1811 tvb
, 0, ADDRESS_INDICATOR_LENGTH
, natl_use_bit
);
1814 routing_ind
= tvb_get_guint8(tvb
, 0) & ROUTING_INDICATOR_MASK
;
1815 proto_tree_add_uint(call_ai_tree
, called
? hf_sccp_called_routing_indicator
: hf_sccp_calling_routing_indicator
,
1816 tvb
, 0, ADDRESS_INDICATOR_LENGTH
, routing_ind
);
1817 /* Only shift off the other bits after adding the item */
1818 routing_ind
>>= ROUTING_INDICATOR_SHIFT
;
1820 gti
= tvb_get_guint8(tvb
, 0) & GTI_MASK
;
1822 if (decode_mtp3_standard
== ITU_STANDARD
||
1823 decode_mtp3_standard
== CHINESE_ITU_STANDARD
||
1824 decode_mtp3_standard
== JAPAN_STANDARD
||
1827 proto_tree_add_uint(call_ai_tree
,
1828 called
? hf_sccp_called_itu_global_title_indicator
: hf_sccp_calling_itu_global_title_indicator
,
1829 tvb
, 0, ADDRESS_INDICATOR_LENGTH
, gti
);
1831 ssni
= tvb_get_guint8(tvb
, 0) & ITU_SSN_INDICATOR_MASK
;
1832 expert_item
= proto_tree_add_uint(call_ai_tree
,
1833 called
? hf_sccp_called_itu_ssn_indicator
: hf_sccp_calling_itu_ssn_indicator
,
1834 tvb
, 0, ADDRESS_INDICATOR_LENGTH
, ssni
);
1835 if ((routing_ind
== ROUTE_ON_SSN
) && (ssni
== 0)) {
1836 expert_add_info(pinfo
, expert_item
, &ei_sccp_no_ssn_present
);
1839 pci
= tvb_get_guint8(tvb
, 0) & ITU_PC_INDICATOR_MASK
;
1840 proto_tree_add_uint(call_ai_tree
, called
? hf_sccp_called_itu_point_code_indicator
: hf_sccp_calling_itu_point_code_indicator
,
1841 tvb
, 0, ADDRESS_INDICATOR_LENGTH
, pci
);
1843 offset
= ADDRESS_INDICATOR_LENGTH
;
1845 /* Dissect PC (if present) */
1847 if (decode_mtp3_standard
== ITU_STANDARD
|| national
== 0) {
1848 if (length
< offset
+ ITU_PC_LENGTH
) {
1849 proto_tree_add_expert_format(call_tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, -1,
1850 "Wrong length indicated (%u) should be at least %u, PC is %u octets",
1851 length
, offset
+ ITU_PC_LENGTH
, ITU_PC_LENGTH
);
1854 proto_tree_add_item(call_tree
, called
? hf_sccp_called_itu_pc
: hf_sccp_calling_itu_pc
,
1855 tvb
, offset
, ITU_PC_LENGTH
, ENC_LITTLE_ENDIAN
);
1856 offset
+= ITU_PC_LENGTH
;
1858 } else if (decode_mtp3_standard
== JAPAN_STANDARD
) {
1860 if (length
< offset
+ JAPAN_PC_LENGTH
) {
1861 proto_tree_add_expert_format(call_tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, -1,
1862 "Wrong length indicated (%u) should be at least %u, PC is %u octets",
1863 length
, offset
+ JAPAN_PC_LENGTH
, JAPAN_PC_LENGTH
);
1866 proto_tree_add_item(call_tree
, called
? hf_sccp_called_japan_pc
: hf_sccp_calling_japan_pc
,
1867 tvb
, offset
, JAPAN_PC_LENGTH
, ENC_LITTLE_ENDIAN
);
1869 offset
+= JAPAN_PC_LENGTH
;
1871 } else /* CHINESE_ITU_STANDARD */ {
1873 if (length
< offset
+ ANSI_PC_LENGTH
) {
1874 proto_tree_add_expert_format(call_tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, -1,
1875 "Wrong length indicated (%u) should be at least %u, PC is %u octets",
1876 length
, offset
+ ANSI_PC_LENGTH
, ANSI_PC_LENGTH
);
1879 offset
= dissect_sccp_3byte_pc(tvb
, call_tree
, offset
, called
);
1884 /* Dissect SSN (if present) */
1886 ssn
= tvb_get_guint8(tvb
, offset
);
1888 if ((routing_ind
== ROUTE_ON_SSN
) && (ssn
== 0)) {
1889 expert_add_info(pinfo
, expert_item
, &ei_sccp_ssn_zero
);
1892 if (called
&& assoc
)
1893 assoc
->called_ssn
= ssn
;
1895 assoc
->calling_ssn
= ssn
;
1897 if (is_connectionless(message_type
) && sccp_msg
) {
1898 guint
*ssn_ptr
= called
? &(sccp_msg
->data
.ud
.called_ssn
) : &(sccp_msg
->data
.ud
.calling_ssn
);
1903 proto_tree_add_uint(call_tree
, called
? hf_sccp_called_ssn
1904 : hf_sccp_calling_ssn
,
1905 tvb
, offset
, ADDRESS_SSN_LENGTH
, ssn
);
1906 hidden_item
= proto_tree_add_uint(call_tree
, hf_sccp_ssn
, tvb
, offset
,
1907 ADDRESS_SSN_LENGTH
, ssn
);
1908 PROTO_ITEM_SET_HIDDEN(hidden_item
);
1910 offset
+= ADDRESS_SSN_LENGTH
;
1912 /* Get the dissector handle of the dissector registered for this ssn
1913 * And print its name.
1915 ssn_dissector
= dissector_get_uint_handle(sccp_ssn_dissector_table
, ssn
);
1917 if (ssn_dissector
) {
1918 ssn_dissector_short_name
= dissector_handle_get_short_name(ssn_dissector
);
1920 if (ssn_dissector_short_name
) {
1921 item
= proto_tree_add_text(call_tree
, tvb
, offset
- 1, ADDRESS_SSN_LENGTH
,
1922 "Linked to %s", ssn_dissector_short_name
);
1923 PROTO_ITEM_SET_GENERATED(item
);
1925 if (g_ascii_strncasecmp("TCAP", ssn_dissector_short_name
, 4)== 0) {
1926 tcap_ssn_dissector
= get_itu_tcap_subdissector(ssn
);
1928 if (tcap_ssn_dissector
) {
1929 tcap_ssn_dissector_short_name
= dissector_handle_get_short_name(tcap_ssn_dissector
);
1930 proto_item_append_text(item
,", TCAP SSN linked to %s", tcap_ssn_dissector_short_name
);
1934 } /* ssn_dissector */
1937 /* Dissect GT (if present) */
1938 if (gti
!= AI_GTI_NO_GT
) {
1939 if (length
< offset
)
1942 gt_tvb
= tvb_new_subset(tvb
, offset
, (length
- offset
),
1944 dissect_sccp_global_title(gt_tvb
, pinfo
, call_tree
, (length
- offset
), gti
,
1945 (routing_ind
== ROUTE_ON_GT
), called
);
1948 } else if (decode_mtp3_standard
== ANSI_STANDARD
) {
1950 proto_tree_add_uint(call_ai_tree
, called
? hf_sccp_called_ansi_global_title_indicator
1951 : hf_sccp_calling_ansi_global_title_indicator
,
1952 tvb
, 0, ADDRESS_INDICATOR_LENGTH
, gti
);
1954 pci
= tvb_get_guint8(tvb
, 0) & ANSI_PC_INDICATOR_MASK
;
1955 proto_tree_add_uint(call_ai_tree
, called
? hf_sccp_called_ansi_point_code_indicator
1956 : hf_sccp_calling_ansi_point_code_indicator
,
1957 tvb
, 0, ADDRESS_INDICATOR_LENGTH
, pci
);
1959 ssni
= tvb_get_guint8(tvb
, 0) & ANSI_SSN_INDICATOR_MASK
;
1960 expert_item
= proto_tree_add_uint(call_ai_tree
, called
? hf_sccp_called_ansi_ssn_indicator
1961 : hf_sccp_calling_ansi_ssn_indicator
,
1962 tvb
, 0, ADDRESS_INDICATOR_LENGTH
, ssni
);
1963 if ((routing_ind
== ROUTE_ON_SSN
) && (ssni
== 0)) {
1964 expert_add_info(pinfo
, expert_item
, &ei_sccp_no_ssn_present
);
1967 offset
= ADDRESS_INDICATOR_LENGTH
;
1969 /* Dissect SSN (if present) */
1971 ssn
= tvb_get_guint8(tvb
, offset
);
1973 if ((routing_ind
== ROUTE_ON_SSN
) && (ssn
== 0)) {
1974 expert_add_info(pinfo
, expert_item
, &ei_sccp_ssn_zero
);
1977 if (called
&& assoc
) {
1978 assoc
->called_ssn
= ssn
;
1980 assoc
->calling_ssn
= ssn
;
1983 if (is_connectionless(message_type
) && sccp_msg
) {
1984 guint
*ssn_ptr
= called
? &(sccp_msg
->data
.ud
.called_ssn
) : &(sccp_msg
->data
.ud
.calling_ssn
);
1989 proto_tree_add_uint(call_tree
, called
? hf_sccp_called_ssn
1990 : hf_sccp_calling_ssn
,
1991 tvb
, offset
, ADDRESS_SSN_LENGTH
, ssn
);
1992 hidden_item
= proto_tree_add_uint(call_tree
, hf_sccp_ssn
, tvb
, offset
,
1993 ADDRESS_SSN_LENGTH
, ssn
);
1994 PROTO_ITEM_SET_HIDDEN(hidden_item
);
1996 offset
+= ADDRESS_SSN_LENGTH
;
1999 /* Dissect PC (if present) */
2001 offset
= dissect_sccp_3byte_pc(tvb
, call_tree
, offset
, called
);
2004 /* Dissect GT (if present) */
2005 if (gti
!= AI_GTI_NO_GT
) {
2006 if (length
< offset
)
2008 gt_tvb
= tvb_new_subset(tvb
, offset
, (length
- offset
),
2010 dissect_sccp_global_title(gt_tvb
, pinfo
, call_tree
, (length
- offset
), gti
,
2011 (routing_ind
== ROUTE_ON_GT
), called
);
2019 dissect_sccp_called_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2021 dissect_sccp_called_calling_param(tvb
, tree
, pinfo
, length
, TRUE
);
2025 dissect_sccp_calling_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2027 dissect_sccp_called_calling_param(tvb
, tree
, pinfo
, length
, FALSE
);
2031 dissect_sccp_class_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2035 gboolean invalid_class
= FALSE
;
2038 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2039 "Wrong length indicated. Expected 1, got %u", length
);
2043 msg_class
= tvb_get_guint8(tvb
, 0) & CLASS_CLASS_MASK
;
2044 pi
= proto_tree_add_uint(tree
, hf_sccp_class
, tvb
, 0, length
, msg_class
);
2046 switch (message_type
) {
2047 case SCCP_MSG_TYPE_DT1
:
2049 invalid_class
= TRUE
;
2051 case SCCP_MSG_TYPE_DT2
:
2052 case SCCP_MSG_TYPE_AK
:
2053 case SCCP_MSG_TYPE_ED
:
2054 case SCCP_MSG_TYPE_EA
:
2055 case SCCP_MSG_TYPE_RSR
:
2056 case SCCP_MSG_TYPE_RSC
:
2058 invalid_class
= TRUE
;
2060 case SCCP_MSG_TYPE_CR
:
2061 case SCCP_MSG_TYPE_CC
:
2062 case SCCP_MSG_TYPE_CREF
:
2063 case SCCP_MSG_TYPE_RLSD
:
2064 case SCCP_MSG_TYPE_RLC
:
2065 case SCCP_MSG_TYPE_ERR
:
2066 case SCCP_MSG_TYPE_IT
:
2067 if ((msg_class
!= 2) && (msg_class
!= 3))
2068 invalid_class
= TRUE
;
2070 case SCCP_MSG_TYPE_UDT
:
2071 case SCCP_MSG_TYPE_UDTS
:
2072 case SCCP_MSG_TYPE_XUDT
:
2073 case SCCP_MSG_TYPE_XUDTS
:
2074 case SCCP_MSG_TYPE_LUDT
:
2075 case SCCP_MSG_TYPE_LUDTS
:
2076 if ((msg_class
!= 0) && (msg_class
!= 1))
2077 invalid_class
= TRUE
;
2082 expert_add_info(pinfo
, pi
, &ei_sccp_class_unexpected
);
2084 if (msg_class
== 0 || msg_class
== 1) {
2085 guint8 handling
= tvb_get_guint8(tvb
, 0) & CLASS_SPARE_HANDLING_MASK
;
2087 pi
= proto_tree_add_item(tree
, hf_sccp_handling
, tvb
, 0, length
, ENC_NA
);
2088 handling
>>= CLASS_SPARE_HANDLING_SHIFT
;
2090 if (try_val_to_str(handling
, sccp_class_handling_values
) == NULL
) {
2091 expert_add_info(pinfo
, pi
, &ei_sccp_handling_invalid
);
2097 dissect_sccp_segmenting_reassembling_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2100 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2101 "Wrong length indicated. Expected 1, got %u", length
);
2105 proto_tree_add_item(tree
, hf_sccp_more
, tvb
, 0, length
, ENC_BIG_ENDIAN
);
2109 dissect_sccp_receive_sequence_number_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2114 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2115 "Wrong length indicated. Expected 1, got %u", length
);
2119 rsn
= tvb_get_guint8(tvb
, 0) >> 1;
2120 proto_tree_add_uint(tree
, hf_sccp_rsn
, tvb
, 0, length
, rsn
);
2124 dissect_sccp_sequencing_segmenting_param(tvbuff_t
*tvb
, proto_tree
*tree
, guint length
)
2127 proto_item
*param_item
;
2128 proto_tree
*param_tree
;
2130 ssn
= tvb_get_guint8(tvb
, 0) >> 1;
2131 rsn
= tvb_get_guint8(tvb
, SEQUENCING_SEGMENTING_SSN_LENGTH
) >> 1;
2133 param_item
= proto_tree_add_text(tree
, tvb
, 0, length
, "%s",
2134 val_to_str(PARAMETER_SEQUENCING_SEGMENTING
,
2135 sccp_parameter_values
, "Unknown: %d"));
2136 param_tree
= proto_item_add_subtree(param_item
,
2137 ett_sccp_sequencing_segmenting
);
2139 proto_tree_add_uint(param_tree
, hf_sccp_sequencing_segmenting_ssn
, tvb
, 0,
2140 SEQUENCING_SEGMENTING_SSN_LENGTH
, ssn
);
2141 proto_tree_add_uint(param_tree
, hf_sccp_sequencing_segmenting_rsn
, tvb
,
2142 SEQUENCING_SEGMENTING_SSN_LENGTH
,
2143 SEQUENCING_SEGMENTING_RSN_LENGTH
, rsn
);
2144 proto_tree_add_item(param_tree
, hf_sccp_sequencing_segmenting_more
, tvb
,
2145 SEQUENCING_SEGMENTING_SSN_LENGTH
,
2146 SEQUENCING_SEGMENTING_RSN_LENGTH
, ENC_NA
);
2150 dissect_sccp_credit_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2153 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2154 "Wrong length indicated. Expected 1, got %u", length
);
2158 proto_tree_add_item(tree
, hf_sccp_credit
, tvb
, 0, length
, ENC_NA
);
2162 dissect_sccp_release_cause_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2165 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2166 "Wrong length indicated. Expected 1, got %u", length
);
2170 proto_tree_add_item(tree
, hf_sccp_release_cause
, tvb
, 0, length
, ENC_LITTLE_ENDIAN
);
2172 if (show_key_params
)
2173 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Cause=%d ", tvb_get_guint8(tvb
, 0));
2177 dissect_sccp_return_cause_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2180 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2181 "Wrong length indicated. Expected 1, got %u", length
);
2185 proto_tree_add_item(tree
, hf_sccp_return_cause
, tvb
, 0, length
, ENC_LITTLE_ENDIAN
);
2187 if (show_key_params
)
2188 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Cause=%d ", tvb_get_guint8(tvb
, 0));
2192 dissect_sccp_reset_cause_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2195 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2196 "Wrong length indicated. Expected 1, got %u", length
);
2200 proto_tree_add_item(tree
, hf_sccp_reset_cause
, tvb
, 0, length
, ENC_LITTLE_ENDIAN
);
2202 if (show_key_params
)
2203 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Cause=%d ", tvb_get_guint8(tvb
, 0));
2207 dissect_sccp_error_cause_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2210 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2211 "Wrong length indicated. Expected 1, got %u", length
);
2215 proto_tree_add_item(tree
, hf_sccp_error_cause
, tvb
, 0, length
, ENC_LITTLE_ENDIAN
);
2217 if (show_key_params
)
2218 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Cause=%d ", tvb_get_guint8(tvb
, 0));
2222 dissect_sccp_refusal_cause_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2225 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2226 "Wrong length indicated. Expected 1, got %u", length
);
2230 proto_tree_add_item(tree
, hf_sccp_refusal_cause
, tvb
, 0, length
, ENC_LITTLE_ENDIAN
);
2232 if (show_key_params
)
2233 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Cause=%d ", tvb_get_guint8(tvb
, 0));
2237 /* This function is used for both data and long data (ITU only) parameters */
2239 dissect_sccp_data_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
2241 guint8 ssn
= INVALID_SSN
;
2242 guint8 other_ssn
= INVALID_SSN
;
2243 const mtp3_addr_pc_t
*dpc
= NULL
;
2244 const mtp3_addr_pc_t
*opc
= NULL
;
2246 if ((trace_sccp
) && (assoc
&& assoc
!= &no_assoc
)) {
2247 pinfo
->sccp_info
= assoc
->curr_msg
;
2249 pinfo
->sccp_info
= NULL
;
2253 switch (pinfo
->p2p_dir
) {
2255 ssn
= assoc
->calling_ssn
;
2256 other_ssn
= assoc
->called_ssn
;
2257 dpc
= (const mtp3_addr_pc_t
*)pinfo
->dst
.data
;
2258 opc
= (const mtp3_addr_pc_t
*)pinfo
->src
.data
;
2261 ssn
= assoc
->called_ssn
;
2262 other_ssn
= assoc
->calling_ssn
;
2263 dpc
= (const mtp3_addr_pc_t
*)pinfo
->src
.data
;
2264 opc
= (const mtp3_addr_pc_t
*)pinfo
->dst
.data
;
2267 ssn
= assoc
->called_ssn
;
2268 other_ssn
= assoc
->calling_ssn
;
2269 dpc
= (const mtp3_addr_pc_t
*)pinfo
->dst
.data
;
2270 opc
= (const mtp3_addr_pc_t
*)pinfo
->src
.data
;
2276 if ((num_sccp_users
) && (pinfo
->src
.type
== AT_SS7PC
)) {
2278 dissector_handle_t handle
= NULL
;
2279 gboolean uses_tcap
= FALSE
;
2281 for (i
=0; i
< num_sccp_users
; i
++) {
2282 sccp_user_t
*u
= &(sccp_users
[i
]);
2284 if (!dpc
|| dpc
->ni
!= u
->ni
) continue;
2286 if (value_is_in_range(u
->called_ssn
, ssn
) && value_is_in_range(u
->called_pc
, dpc
->pc
) ) {
2287 handle
= *(u
->handlep
);
2288 uses_tcap
= u
->uses_tcap
;
2290 } else if (value_is_in_range(u
->called_ssn
, other_ssn
) && opc
&& value_is_in_range(u
->called_pc
, opc
->pc
) ) {
2291 handle
= *(u
->handlep
);
2292 uses_tcap
= u
->uses_tcap
;
2299 call_tcap_dissector(handle
, tvb
, pinfo
, tree
);
2301 call_dissector(handle
, tvb
, pinfo
, tree
);
2308 if ((ssn
!= INVALID_SSN
) && dissector_try_uint(sccp_ssn_dissector_table
, ssn
, tvb
, pinfo
, tree
)) {
2312 if ((other_ssn
!= INVALID_SSN
) && dissector_try_uint(sccp_ssn_dissector_table
, other_ssn
, tvb
, pinfo
, tree
)) {
2316 /* try heuristic subdissector list to see if there are any takers */
2317 if (dissector_try_heuristic(heur_subdissector_list
, tvb
, pinfo
, tree
, NULL
)) {
2321 /* try user default subdissector */
2322 if (default_handle
) {
2323 call_dissector(default_handle
, tvb
, pinfo
, tree
);
2327 /* No sub-dissection occurred, treat it as raw data */
2328 call_dissector(data_handle
, tvb
, pinfo
, tree
);
2333 dissect_sccp_segmentation_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2335 proto_item
*param_item
;
2336 proto_tree
*param_tree
;
2338 param_item
= proto_tree_add_text(tree
, tvb
, 0, length
, "%s",
2339 val_to_str(PARAMETER_SEGMENTATION
,
2340 sccp_parameter_values
, "Unknown: %d"));
2341 param_tree
= proto_item_add_subtree(param_item
, ett_sccp_segmentation
);
2343 proto_tree_add_item(param_tree
, hf_sccp_segmentation_first
, tvb
, 0, 1, ENC_NA
);
2344 proto_tree_add_item(param_tree
, hf_sccp_segmentation_class
, tvb
, 0, 1, ENC_NA
);
2345 proto_tree_add_item(param_tree
, hf_sccp_segmentation_remaining
, tvb
, 0, 1, ENC_NA
);
2347 if (length
-1 != 3) {
2348 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
-1,
2349 "Wrong length indicated. Expected 3, got %u", length
-1);
2353 proto_tree_add_item(param_tree
, hf_sccp_segmentation_slr
, tvb
, 1, length
-1, ENC_LITTLE_ENDIAN
);
2357 dissect_sccp_hop_counter_param(tvbuff_t
*tvb
, proto_tree
*tree
, guint length
)
2361 hops
= tvb_get_guint8(tvb
, 0);
2362 proto_tree_add_uint(tree
, hf_sccp_hop_counter
, tvb
, 0, length
, hops
);
2366 dissect_sccp_importance_param(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint length
)
2369 proto_tree_add_expert_format(tree
, pinfo
, &ei_sccp_wrong_length
, tvb
, 0, length
,
2370 "Wrong length indicated. Expected 1, got %u", length
);
2374 proto_tree_add_item(tree
, hf_sccp_importance
, tvb
, 0, length
, ENC_NA
);
2378 dissect_sccp_isni_param(tvbuff_t
*tvb
, proto_tree
*tree
, guint length
)
2382 proto_item
*param_item
;
2383 proto_tree
*param_tree
;
2385 /* Create a subtree for ISNI Routing Control */
2386 param_item
= proto_tree_add_text(tree
, tvb
, offset
, ANSI_ISNI_ROUTING_CONTROL_LENGTH
,
2387 "ISNI Routing Control");
2388 param_tree
= proto_item_add_subtree(param_item
,
2389 ett_sccp_ansi_isni_routing_control
);
2391 proto_tree_add_item(param_tree
, hf_sccp_ansi_isni_mi
, tvb
, offset
,
2392 ANSI_ISNI_ROUTING_CONTROL_LENGTH
, ENC_NA
);
2394 proto_tree_add_item(param_tree
, hf_sccp_ansi_isni_iri
, tvb
, offset
,
2395 ANSI_ISNI_ROUTING_CONTROL_LENGTH
, ENC_NA
);
2397 ti
= tvb_get_guint8(tvb
, offset
) & ANSI_ISNI_TI_MASK
;
2398 proto_tree_add_uint(param_tree
, hf_sccp_ansi_isni_ti
, tvb
, offset
,
2399 ANSI_ISNI_ROUTING_CONTROL_LENGTH
, ti
);
2401 proto_tree_add_item(param_tree
, hf_sccp_ansi_isni_counter
, tvb
, offset
,
2402 ANSI_ISNI_ROUTING_CONTROL_LENGTH
, ENC_NA
);
2404 offset
+= ANSI_ISNI_ROUTING_CONTROL_LENGTH
;
2406 if ((ti
>> ANSI_ISNI_TI_SHIFT
) == ANSI_ISNI_TYPE_1
) {
2407 proto_tree_add_uint(param_tree
, hf_sccp_ansi_isni_netspec
, tvb
, offset
,
2408 ANSI_ISNI_ROUTING_CONTROL_LENGTH
, ti
);
2409 offset
+= ANSI_ISNI_ROUTING_CONTROL_LENGTH
;
2412 while (offset
< length
) {
2414 proto_tree_add_item(tree
, hf_sccp_ansi_isni_network
, tvb
, offset
,
2415 ANSI_NCM_LENGTH
, ENC_NA
);
2418 proto_tree_add_item(tree
, hf_sccp_ansi_isni_cluster
, tvb
, offset
,
2419 ANSI_NCM_LENGTH
, ENC_NA
);
2425 /* FUNCTION dissect_sccp_parameter():
2426 * Dissect a parameter given its type, offset into tvb, and length.
2429 dissect_sccp_parameter(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*sccp_tree
,
2430 proto_tree
*tree
, guint8 parameter_type
, guint16 offset
,
2431 guint16 parameter_length
)
2433 tvbuff_t
*parameter_tvb
;
2435 switch (parameter_type
) {
2436 case PARAMETER_CALLED_PARTY_ADDRESS
:
2437 case PARAMETER_CALLING_PARTY_ADDRESS
:
2438 case PARAMETER_DATA
:
2439 case PARAMETER_LONG_DATA
:
2440 case PARAMETER_SOURCE_LOCAL_REFERENCE
:
2441 case PARAMETER_DESTINATION_LOCAL_REFERENCE
:
2442 case PARAMETER_RELEASE_CAUSE
:
2443 case PARAMETER_RETURN_CAUSE
:
2444 case PARAMETER_RESET_CAUSE
:
2445 case PARAMETER_ERROR_CAUSE
:
2446 case PARAMETER_REFUSAL_CAUSE
:
2448 /* These parameters must be dissected even if !sccp_tree (so that
2449 * assoc information can be created).
2454 if (!sccp_tree
) return(parameter_length
);
2458 parameter_tvb
= tvb_new_subset(tvb
, offset
, parameter_length
, parameter_length
);
2460 switch (parameter_type
) {
2462 case PARAMETER_END_OF_OPTIONAL_PARAMETERS
:
2463 proto_tree_add_text(sccp_tree
, tvb
, offset
, parameter_length
,
2467 case PARAMETER_DESTINATION_LOCAL_REFERENCE
:
2468 dissect_sccp_dlr_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2471 case PARAMETER_SOURCE_LOCAL_REFERENCE
:
2472 dissect_sccp_slr_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2475 case PARAMETER_CALLED_PARTY_ADDRESS
:
2476 dissect_sccp_called_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2479 case PARAMETER_CALLING_PARTY_ADDRESS
:
2480 dissect_sccp_calling_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2483 case PARAMETER_CLASS
:
2484 dissect_sccp_class_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2487 case PARAMETER_SEGMENTING_REASSEMBLING
:
2488 dissect_sccp_segmenting_reassembling_param(parameter_tvb
, pinfo
, sccp_tree
,
2492 case PARAMETER_RECEIVE_SEQUENCE_NUMBER
:
2493 dissect_sccp_receive_sequence_number_param(parameter_tvb
, pinfo
, sccp_tree
,
2497 case PARAMETER_SEQUENCING_SEGMENTING
:
2498 dissect_sccp_sequencing_segmenting_param(parameter_tvb
, sccp_tree
,
2502 case PARAMETER_CREDIT
:
2503 dissect_sccp_credit_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2506 case PARAMETER_RELEASE_CAUSE
:
2507 dissect_sccp_release_cause_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2510 case PARAMETER_RETURN_CAUSE
:
2511 dissect_sccp_return_cause_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2514 case PARAMETER_RESET_CAUSE
:
2515 dissect_sccp_reset_cause_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2518 case PARAMETER_ERROR_CAUSE
:
2519 dissect_sccp_error_cause_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2522 case PARAMETER_REFUSAL_CAUSE
:
2523 dissect_sccp_refusal_cause_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2526 case PARAMETER_DATA
:
2527 dissect_sccp_data_param(parameter_tvb
, pinfo
, tree
);
2529 /* TODO? Re-adjust length of SCCP item since it may be sub-dissected */
2530 /* sccp_length = proto_item_get_len(sccp_item);
2531 * sccp_length -= parameter_length;
2532 * proto_item_set_len(sccp_item, sccp_length);
2536 case PARAMETER_SEGMENTATION
:
2537 dissect_sccp_segmentation_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2540 case PARAMETER_HOP_COUNTER
:
2541 dissect_sccp_hop_counter_param(parameter_tvb
, sccp_tree
, parameter_length
);
2544 case PARAMETER_IMPORTANCE
:
2545 if (decode_mtp3_standard
!= ANSI_STANDARD
)
2546 dissect_sccp_importance_param(parameter_tvb
, pinfo
, sccp_tree
, parameter_length
);
2548 dissect_sccp_unknown_param(parameter_tvb
, sccp_tree
, parameter_type
,
2552 case PARAMETER_LONG_DATA
:
2553 dissect_sccp_data_param(parameter_tvb
, pinfo
, tree
);
2556 case PARAMETER_ISNI
:
2557 if (decode_mtp3_standard
!= ANSI_STANDARD
)
2558 dissect_sccp_unknown_param(parameter_tvb
, sccp_tree
, parameter_type
,
2561 dissect_sccp_isni_param(parameter_tvb
, sccp_tree
, parameter_length
);
2565 dissect_sccp_unknown_param(parameter_tvb
, sccp_tree
, parameter_type
,
2570 return(parameter_length
);
2573 /* FUNCTION dissect_sccp_variable_parameter():
2574 * Dissect a variable parameter given its type and offset into tvb. Length
2575 * of the parameter is gotten from tvb[0].
2576 * Length returned is sum of (length + parameter).
2579 dissect_sccp_variable_parameter(tvbuff_t
*tvb
, packet_info
*pinfo
,
2580 proto_tree
*sccp_tree
, proto_tree
*tree
,
2581 guint8 parameter_type
, guint16 offset
)
2583 guint16 parameter_length
;
2584 guint8 length_length
;
2587 if (parameter_type
!= PARAMETER_LONG_DATA
) {
2588 parameter_length
= tvb_get_guint8(tvb
, offset
);
2589 length_length
= PARAMETER_LENGTH_LENGTH
;
2591 /* Long data parameter has 16 bit length */
2592 parameter_length
= tvb_get_letohs(tvb
, offset
);
2593 length_length
= PARAMETER_LONG_DATA_LENGTH_LENGTH
;
2596 pi
= proto_tree_add_uint_format(sccp_tree
, hf_sccp_param_length
, tvb
, offset
,
2597 length_length
, parameter_length
, "%s length: %d",
2598 val_to_str(parameter_type
, sccp_parameter_values
,
2601 if (!sccp_show_length
) {
2602 /* The user doesn't want to see it... */
2603 PROTO_ITEM_SET_HIDDEN(pi
);
2606 offset
+= length_length
;
2608 dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
, parameter_type
, offset
,
2611 return(parameter_length
+ length_length
);
2614 /* FUNCTION dissect_sccp_optional_parameters():
2615 * Dissect all the optional parameters given the start of the optional
2616 * parameters into tvb. Parameter types and lengths are read from tvb.
2619 dissect_sccp_optional_parameters(tvbuff_t
*tvb
, packet_info
*pinfo
,
2620 proto_tree
*sccp_tree
, proto_tree
*tree
,
2623 guint8 parameter_type
;
2625 while ((parameter_type
= tvb_get_guint8(tvb
, offset
)) !=
2626 PARAMETER_END_OF_OPTIONAL_PARAMETERS
) {
2628 offset
+= PARAMETER_TYPE_LENGTH
;
2629 offset
+= dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2630 parameter_type
, offset
);
2633 /* Process end of optional parameters */
2634 dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
, parameter_type
, offset
,
2635 END_OF_OPTIONAL_PARAMETERS_LENGTH
);
2639 static sccp_msg_info_t
*
2640 new_ud_msg(packet_info
*pinfo
, guint32 msg_type _U_
)
2642 sccp_msg_info_t
*m
= wmem_new0(wmem_packet_scope(), sccp_msg_info_t
);
2643 m
->framenum
= PINFO_FD_NUM(pinfo
);
2644 m
->data
.ud
.calling_gt
= NULL
;
2645 m
->data
.ud
.called_gt
= NULL
;
2647 register_frame_end_routine(pinfo
, reset_sccp_assoc
);
2652 dissect_sccp_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*sccp_tree
,
2655 guint16 variable_pointer1
= 0, variable_pointer2
= 0, variable_pointer3
= 0;
2656 guint16 optional_pointer
= 0, orig_opt_ptr
= 0;
2658 gboolean save_fragmented
;
2659 tvbuff_t
*new_tvb
= NULL
;
2660 fragment_head
*frag_msg
= NULL
;
2661 guint32 source_local_ref
= 0;
2663 guint msg_offset
= tvb_offset_from_real_beginning(tvb
);
2665 /* Macro for getting pointer to mandatory variable parameters */
2666 #define VARIABLE_POINTER(var, hf_var, ptr_size) \
2668 if (ptr_size == POINTER_LENGTH) \
2669 var = tvb_get_guint8(tvb, offset); \
2671 var = tvb_get_letohs(tvb, offset); \
2672 proto_tree_add_uint(sccp_tree, hf_var, tvb, \
2673 offset, ptr_size, var); \
2675 if (ptr_size == POINTER_LENGTH_LONG) \
2677 offset += ptr_size; \
2680 /* Macro for getting pointer to optional parameters */
2681 #define OPTIONAL_POINTER(ptr_size) \
2683 if (ptr_size == POINTER_LENGTH) \
2684 orig_opt_ptr = optional_pointer = tvb_get_guint8(tvb, offset); \
2686 orig_opt_ptr = optional_pointer = tvb_get_letohs(tvb, offset); \
2687 proto_tree_add_uint(sccp_tree, hf_sccp_optional_pointer, tvb, \
2688 offset, ptr_size, optional_pointer); \
2689 optional_pointer += offset; \
2690 if (ptr_size == POINTER_LENGTH_LONG) \
2691 optional_pointer += 1; \
2692 offset += ptr_size; \
2696 /* Extract the message type; all other processing is based on this */
2697 message_type
= tvb_get_guint8(tvb
, SCCP_MSG_TYPE_OFFSET
);
2698 offset
= SCCP_MSG_TYPE_LENGTH
;
2700 /* Do not change col_add_fstr() to col_append_fstr() here: we _want_
2701 * this call to overwrite whatever's currently in the INFO column (e.g.,
2702 * "DATA" from the SCTP dissector).
2704 * If there's something there that should not be overwritten, whoever
2705 * put that info there should call col_set_fence() to protect it.
2707 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s ",
2708 val_to_str(message_type
, sccp_message_type_acro_values
, "Unknown: %d"));
2711 /* add the message type to the protocol tree */
2712 proto_tree_add_uint(sccp_tree
, hf_sccp_message_type
, tvb
,
2713 SCCP_MSG_TYPE_OFFSET
, SCCP_MSG_TYPE_LENGTH
, message_type
);
2717 /* Starting a new message dissection; clear the global assoc, SLR, and DLR values */
2722 no_assoc
.calling_dpc
= 0;
2723 no_assoc
.called_dpc
= 0;
2724 no_assoc
.calling_ssn
= INVALID_SSN
;
2725 no_assoc
.called_ssn
= INVALID_SSN
;
2726 no_assoc
.has_fw_key
= FALSE
;
2727 no_assoc
.has_bw_key
= FALSE
;
2728 no_assoc
.payload
= SCCP_PLOAD_NONE
;
2729 no_assoc
.called_party
= NULL
;
2730 no_assoc
.calling_party
= NULL
;
2731 no_assoc
.extra_info
= NULL
;
2733 switch (message_type
) {
2734 case SCCP_MSG_TYPE_CR
:
2735 /* TTC and NTT (Japan) say that the connection-oriented messages are
2736 * deleted (not standardized), but they appear to be used anyway, so
2737 * we'll dissect it...
2739 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2740 PARAMETER_SOURCE_LOCAL_REFERENCE
,
2741 offset
, SOURCE_LOCAL_REFERENCE_LENGTH
);
2742 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2743 PARAMETER_CLASS
, offset
,
2744 PROTOCOL_CLASS_LENGTH
);
2745 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2747 VARIABLE_POINTER(variable_pointer1
, hf_sccp_variable_pointer1
, POINTER_LENGTH
);
2748 OPTIONAL_POINTER(POINTER_LENGTH
);
2750 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2751 PARAMETER_CALLED_PARTY_ADDRESS
,
2755 case SCCP_MSG_TYPE_CC
:
2756 /* TODO: connection has been established; theoretically we could keep
2757 * keep track of the SLR/DLR with the called/calling from the CR and
2758 * track the connection (e.g., on subsequent messages regarding this
2759 * SLR we could set the global vars "call*_ssn" so data could get
2762 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2763 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
2765 DESTINATION_LOCAL_REFERENCE_LENGTH
);
2766 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2767 PARAMETER_SOURCE_LOCAL_REFERENCE
,
2768 offset
, SOURCE_LOCAL_REFERENCE_LENGTH
);
2770 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2772 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2773 PARAMETER_CLASS
, offset
,
2774 PROTOCOL_CLASS_LENGTH
);
2775 OPTIONAL_POINTER(POINTER_LENGTH
);
2778 case SCCP_MSG_TYPE_CREF
:
2779 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2780 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
2782 DESTINATION_LOCAL_REFERENCE_LENGTH
);
2784 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2786 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2787 PARAMETER_REFUSAL_CAUSE
, offset
,
2788 REFUSAL_CAUSE_LENGTH
);
2789 OPTIONAL_POINTER(POINTER_LENGTH
);
2792 case SCCP_MSG_TYPE_RLSD
:
2793 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2794 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
2796 DESTINATION_LOCAL_REFERENCE_LENGTH
);
2797 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2798 PARAMETER_SOURCE_LOCAL_REFERENCE
,
2799 offset
, SOURCE_LOCAL_REFERENCE_LENGTH
);
2801 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2803 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2804 PARAMETER_RELEASE_CAUSE
, offset
,
2805 RELEASE_CAUSE_LENGTH
);
2807 OPTIONAL_POINTER(POINTER_LENGTH
);
2808 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2811 case SCCP_MSG_TYPE_RLC
:
2812 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2813 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
2815 DESTINATION_LOCAL_REFERENCE_LENGTH
);
2816 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2817 PARAMETER_SOURCE_LOCAL_REFERENCE
,
2818 offset
, SOURCE_LOCAL_REFERENCE_LENGTH
);
2820 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2823 case SCCP_MSG_TYPE_DT1
:
2824 source_local_ref
= tvb_get_letoh24(tvb
, offset
);
2825 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2826 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
2828 DESTINATION_LOCAL_REFERENCE_LENGTH
);
2830 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2832 more
= tvb_get_guint8(tvb
, offset
) & SEGMENTING_REASSEMBLING_MASK
;
2834 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2835 PARAMETER_SEGMENTING_REASSEMBLING
,
2836 offset
, SEGMENTING_REASSEMBLING_LENGTH
);
2837 VARIABLE_POINTER(variable_pointer1
, hf_sccp_variable_pointer1
, POINTER_LENGTH
);
2840 if (!sccp_xudt_desegment
) {
2841 proto_tree_add_text(sccp_tree
, tvb
, variable_pointer1
,
2842 tvb_get_guint8(tvb
, variable_pointer1
)+1,
2844 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2845 PARAMETER_DATA
, variable_pointer1
);
2848 save_fragmented
= pinfo
->fragmented
;
2849 pinfo
->fragmented
= TRUE
;
2850 frag_msg
= fragment_add_seq_next(&sccp_xudt_msg_reassembly_table
,
2851 tvb
, variable_pointer1
+ 1,
2853 source_local_ref
, /* ID for fragments belonging together */
2855 tvb_get_guint8(tvb
, variable_pointer1
), /* fragment length - to the end */
2856 more
); /* More fragments? */
2858 new_tvb
= process_reassembled_data(tvb
, variable_pointer1
+ 1, pinfo
,
2859 "Reassembled SCCP", frag_msg
,
2860 &sccp_xudt_msg_frag_items
, NULL
,
2863 if (frag_msg
&& frag_msg
->next
) { /* Reassembled */
2864 col_append_str(pinfo
->cinfo
, COL_INFO
, "(Message reassembled) ");
2865 } else if (more
) { /* Not last packet of reassembled message */
2866 col_append_str(pinfo
->cinfo
, COL_INFO
, "(Message fragment) ");
2869 pinfo
->fragmented
= save_fragmented
;
2872 dissect_sccp_data_param(new_tvb
, pinfo
, tree
);
2875 /* End reassemble */
2878 case SCCP_MSG_TYPE_DT2
:
2879 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2880 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
2882 DESTINATION_LOCAL_REFERENCE_LENGTH
);
2884 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2886 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2887 PARAMETER_SEQUENCING_SEGMENTING
, offset
,
2888 SEQUENCING_SEGMENTING_LENGTH
);
2891 case SCCP_MSG_TYPE_AK
:
2892 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2893 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
2895 DESTINATION_LOCAL_REFERENCE_LENGTH
);
2897 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2899 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2900 PARAMETER_RECEIVE_SEQUENCE_NUMBER
,
2901 offset
, RECEIVE_SEQUENCE_NUMBER_LENGTH
);
2902 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2903 PARAMETER_CREDIT
, offset
, CREDIT_LENGTH
);
2906 case SCCP_MSG_TYPE_UDT
:
2907 pinfo
->sccp_info
= sccp_msg
= new_ud_msg(pinfo
, message_type
);
2909 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2910 PARAMETER_CLASS
, offset
,
2911 PROTOCOL_CLASS_LENGTH
);
2912 VARIABLE_POINTER(variable_pointer1
, hf_sccp_variable_pointer1
, POINTER_LENGTH
);
2913 VARIABLE_POINTER(variable_pointer2
, hf_sccp_variable_pointer2
, POINTER_LENGTH
);
2914 VARIABLE_POINTER(variable_pointer3
, hf_sccp_variable_pointer3
, POINTER_LENGTH
);
2916 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2918 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2919 PARAMETER_CALLED_PARTY_ADDRESS
,
2921 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2922 PARAMETER_CALLING_PARTY_ADDRESS
,
2925 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
, PARAMETER_DATA
,
2929 case SCCP_MSG_TYPE_UDTS
:
2931 gboolean save_in_error_pkt
= pinfo
->flags
.in_error_pkt
;
2932 pinfo
->flags
.in_error_pkt
= TRUE
;
2934 pinfo
->sccp_info
= sccp_msg
= new_ud_msg(pinfo
, message_type
);
2936 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2937 PARAMETER_RETURN_CAUSE
, offset
,
2938 RETURN_CAUSE_LENGTH
);
2940 VARIABLE_POINTER(variable_pointer1
, hf_sccp_variable_pointer1
, POINTER_LENGTH
);
2941 VARIABLE_POINTER(variable_pointer2
, hf_sccp_variable_pointer2
, POINTER_LENGTH
);
2942 VARIABLE_POINTER(variable_pointer3
, hf_sccp_variable_pointer3
, POINTER_LENGTH
);
2944 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2946 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2947 PARAMETER_CALLED_PARTY_ADDRESS
,
2950 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2951 PARAMETER_CALLING_PARTY_ADDRESS
,
2954 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
, PARAMETER_DATA
,
2956 pinfo
->flags
.in_error_pkt
= save_in_error_pkt
;
2960 case SCCP_MSG_TYPE_ED
:
2961 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2962 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
2964 DESTINATION_LOCAL_REFERENCE_LENGTH
);
2966 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2968 VARIABLE_POINTER(variable_pointer1
, hf_sccp_variable_pointer1
, POINTER_LENGTH
);
2970 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
, PARAMETER_DATA
,
2974 case SCCP_MSG_TYPE_EA
:
2975 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2976 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
2978 DESTINATION_LOCAL_REFERENCE_LENGTH
);
2979 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2982 case SCCP_MSG_TYPE_RSR
:
2983 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2984 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
2986 DESTINATION_LOCAL_REFERENCE_LENGTH
);
2987 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2988 PARAMETER_SOURCE_LOCAL_REFERENCE
,
2989 offset
, SOURCE_LOCAL_REFERENCE_LENGTH
);
2990 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2991 PARAMETER_RESET_CAUSE
, offset
,
2992 RESET_CAUSE_LENGTH
);
2993 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
2996 case SCCP_MSG_TYPE_RSC
:
2997 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
2998 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
3000 DESTINATION_LOCAL_REFERENCE_LENGTH
);
3001 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3002 PARAMETER_SOURCE_LOCAL_REFERENCE
,
3003 offset
, SOURCE_LOCAL_REFERENCE_LENGTH
);
3004 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
3007 case SCCP_MSG_TYPE_ERR
:
3008 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3009 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
3011 DESTINATION_LOCAL_REFERENCE_LENGTH
);
3012 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3013 PARAMETER_ERROR_CAUSE
, offset
,
3014 ERROR_CAUSE_LENGTH
);
3015 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
3018 case SCCP_MSG_TYPE_IT
:
3019 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3020 PARAMETER_DESTINATION_LOCAL_REFERENCE
,
3022 DESTINATION_LOCAL_REFERENCE_LENGTH
);
3023 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3024 PARAMETER_SOURCE_LOCAL_REFERENCE
,
3025 offset
, SOURCE_LOCAL_REFERENCE_LENGTH
);
3026 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
3027 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3028 PARAMETER_CLASS
, offset
,
3029 PROTOCOL_CLASS_LENGTH
);
3030 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3031 PARAMETER_SEQUENCING_SEGMENTING
,
3032 offset
, SEQUENCING_SEGMENTING_LENGTH
);
3033 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3034 PARAMETER_CREDIT
, offset
, CREDIT_LENGTH
);
3037 case SCCP_MSG_TYPE_XUDT
:
3038 pinfo
->sccp_info
= sccp_msg
= new_ud_msg(pinfo
, message_type
);
3039 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3040 PARAMETER_CLASS
, offset
,
3041 PROTOCOL_CLASS_LENGTH
);
3042 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3043 PARAMETER_HOP_COUNTER
, offset
,
3044 HOP_COUNTER_LENGTH
);
3046 VARIABLE_POINTER(variable_pointer1
, hf_sccp_variable_pointer1
, POINTER_LENGTH
);
3047 VARIABLE_POINTER(variable_pointer2
, hf_sccp_variable_pointer2
, POINTER_LENGTH
);
3048 VARIABLE_POINTER(variable_pointer3
, hf_sccp_variable_pointer3
, POINTER_LENGTH
);
3049 OPTIONAL_POINTER(POINTER_LENGTH
);
3051 /* Optional parameters are Segmentation and Importance
3052 * NOTE 2 - Segmentation Should not be present in case of a single XUDT
3056 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
3058 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3059 PARAMETER_CALLED_PARTY_ADDRESS
,
3061 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3062 PARAMETER_CALLING_PARTY_ADDRESS
,
3065 if (tvb_get_guint8(tvb
, optional_pointer
) == PARAMETER_SEGMENTATION
) {
3066 if (!sccp_xudt_desegment
) {
3067 proto_tree_add_text(sccp_tree
, tvb
, variable_pointer3
, tvb_get_guint8(tvb
, variable_pointer3
)+1, "Segmented Data");
3070 gboolean more_frag
= TRUE
;
3072 /* Get the first octet of parameter Segmentation, Ch 3.17 in Q.713
3073 * Bit 8 of octet 1 is used for First segment indication
3074 * Bit 7 of octet 1 is used to keep in the message in sequence
3075 * delivery option required by the SCCP user
3076 * Bits 6 and 5 in octet 1 are spare bits.
3077 * Bits 4-1 of octet 1 are used to indicate the number of
3078 * remaining segments.
3079 * The values 0000 to 1111 are possible; the value 0000 indicates
3082 octet
= tvb_get_guint8(tvb
, optional_pointer
+2);
3083 source_local_ref
= tvb_get_letoh24(tvb
, optional_pointer
+3);
3085 if ((octet
& 0x0f) == 0)
3088 save_fragmented
= pinfo
->fragmented
;
3089 pinfo
->fragmented
= TRUE
;
3090 frag_msg
= fragment_add_seq_next(&sccp_xudt_msg_reassembly_table
,
3091 tvb
, variable_pointer3
+ 1,
3093 source_local_ref
, /* ID for fragments belonging together */
3095 tvb_get_guint8(tvb
, variable_pointer3
), /* fragment length - to the end */
3096 more_frag
); /* More fragments? */
3098 if ((octet
& 0x80) == 0x80) /*First segment, set number of segments*/
3099 fragment_set_tot_len(&sccp_xudt_msg_reassembly_table
,
3100 pinfo
, source_local_ref
, NULL
, (octet
& 0xf));
3102 new_tvb
= process_reassembled_data(tvb
, variable_pointer3
+ 1,
3103 pinfo
, "Reassembled SCCP",
3105 &sccp_xudt_msg_frag_items
,
3108 if (frag_msg
) { /* Reassembled */
3109 col_append_str(pinfo
->cinfo
, COL_INFO
,"(Message reassembled) ");
3110 } else { /* Not last packet of reassembled message */
3111 col_append_str(pinfo
->cinfo
, COL_INFO
,"(Message fragment) ");
3114 pinfo
->fragmented
= save_fragmented
;
3117 dissect_sccp_data_param(new_tvb
, pinfo
, tree
);
3120 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3121 PARAMETER_DATA
, variable_pointer3
);
3125 case SCCP_MSG_TYPE_XUDTS
:
3127 gboolean save_in_error_pkt
= pinfo
->flags
.in_error_pkt
;
3128 pinfo
->flags
.in_error_pkt
= TRUE
;
3130 pinfo
->sccp_info
= sccp_msg
= new_ud_msg(pinfo
, message_type
);
3131 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3132 PARAMETER_RETURN_CAUSE
, offset
,
3133 RETURN_CAUSE_LENGTH
);
3134 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3135 PARAMETER_HOP_COUNTER
, offset
,
3136 HOP_COUNTER_LENGTH
);
3138 VARIABLE_POINTER(variable_pointer1
, hf_sccp_variable_pointer1
, POINTER_LENGTH
);
3139 VARIABLE_POINTER(variable_pointer2
, hf_sccp_variable_pointer2
, POINTER_LENGTH
);
3140 VARIABLE_POINTER(variable_pointer3
, hf_sccp_variable_pointer3
, POINTER_LENGTH
);
3141 OPTIONAL_POINTER(POINTER_LENGTH
);
3143 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
3145 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3146 PARAMETER_CALLED_PARTY_ADDRESS
,
3148 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3149 PARAMETER_CALLING_PARTY_ADDRESS
,
3152 if (tvb_get_guint8(tvb
, optional_pointer
) == PARAMETER_SEGMENTATION
) {
3153 if (!sccp_xudt_desegment
) {
3154 proto_tree_add_text(sccp_tree
, tvb
, variable_pointer3
, tvb_get_guint8(tvb
, variable_pointer3
)+1, "Segmented Data");
3158 gboolean more_frag
= TRUE
;
3161 /* Get the first octet of parameter Segmentation, Ch 3.17 in Q.713
3162 * Bit 8 of octet 1 is used for First segment indication
3163 * Bit 7 of octet 1 is used to keep in the message in sequence
3164 * delivery option required by the SCCP user
3165 * Bits 6 and 5 in octet 1 are spare bits.
3166 * Bits 4-1 of octet 1 are used to indicate the number of
3167 * remaining segments.
3168 * The values 0000 to 1111 are possible; the value 0000 indicates
3171 octet
= tvb_get_guint8(tvb
, optional_pointer
+2);
3172 source_local_ref
= tvb_get_letoh24(tvb
, optional_pointer
+3);
3174 if ((octet
& 0x0f) == 0)
3177 save_fragmented
= pinfo
->fragmented
;
3178 pinfo
->fragmented
= TRUE
;
3179 frag_msg
= fragment_add_seq_next(&sccp_xudt_msg_reassembly_table
,
3180 tvb
, variable_pointer3
+ 1,
3182 source_local_ref
, /* ID for fragments belonging together */
3184 tvb_get_guint8(tvb
, variable_pointer3
), /* fragment length - to the end */
3185 more_frag
); /* More fragments? */
3187 if ((octet
& 0x80) == 0x80) /*First segment, set number of segments*/
3188 fragment_set_tot_len(&sccp_xudt_msg_reassembly_table
,
3189 pinfo
, source_local_ref
, NULL
, (octet
& 0xf));
3191 new_tvb
= process_reassembled_data(tvb
, variable_pointer3
+ 1,
3192 pinfo
, "Reassembled SCCP",
3194 &sccp_xudt_msg_frag_items
,
3197 if (frag_msg
) { /* Reassembled */
3198 col_append_str(pinfo
->cinfo
, COL_INFO
, "(Message reassembled) ");
3199 } else { /* Not last packet of reassembled message */
3200 col_append_str(pinfo
->cinfo
, COL_INFO
, "(Message fragment) ");
3203 pinfo
->fragmented
= save_fragmented
;
3206 dissect_sccp_data_param(new_tvb
, pinfo
, tree
);
3209 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3210 PARAMETER_DATA
, variable_pointer3
);
3212 pinfo
->flags
.in_error_pkt
= save_in_error_pkt
;
3215 case SCCP_MSG_TYPE_LUDT
:
3216 pinfo
->sccp_info
= sccp_msg
= new_ud_msg(pinfo
, message_type
);
3218 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3219 PARAMETER_CLASS
, offset
,
3220 PROTOCOL_CLASS_LENGTH
);
3221 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3222 PARAMETER_HOP_COUNTER
, offset
,
3223 HOP_COUNTER_LENGTH
);
3225 VARIABLE_POINTER(variable_pointer1
, hf_sccp_variable_pointer1
, POINTER_LENGTH_LONG
);
3226 VARIABLE_POINTER(variable_pointer2
, hf_sccp_variable_pointer2
, POINTER_LENGTH_LONG
);
3227 VARIABLE_POINTER(variable_pointer3
, hf_sccp_variable_pointer3
, POINTER_LENGTH_LONG
);
3228 OPTIONAL_POINTER(POINTER_LENGTH_LONG
);
3230 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
3232 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3233 PARAMETER_CALLED_PARTY_ADDRESS
,
3235 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3236 PARAMETER_CALLING_PARTY_ADDRESS
,
3238 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3239 PARAMETER_LONG_DATA
, variable_pointer3
);
3242 case SCCP_MSG_TYPE_LUDTS
:
3243 pinfo
->sccp_info
= sccp_msg
= new_ud_msg(pinfo
, message_type
);
3244 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3245 PARAMETER_RETURN_CAUSE
, offset
,
3246 RETURN_CAUSE_LENGTH
);
3247 offset
+= dissect_sccp_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3248 PARAMETER_HOP_COUNTER
, offset
,
3249 HOP_COUNTER_LENGTH
);
3251 VARIABLE_POINTER(variable_pointer1
, hf_sccp_variable_pointer1
, POINTER_LENGTH_LONG
);
3252 VARIABLE_POINTER(variable_pointer2
, hf_sccp_variable_pointer2
, POINTER_LENGTH_LONG
);
3253 VARIABLE_POINTER(variable_pointer3
, hf_sccp_variable_pointer3
, POINTER_LENGTH_LONG
);
3254 OPTIONAL_POINTER(POINTER_LENGTH_LONG
);
3256 assoc
= get_sccp_assoc(pinfo
, msg_offset
, slr
, dlr
, message_type
);
3258 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3259 PARAMETER_CALLED_PARTY_ADDRESS
,
3261 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3262 PARAMETER_CALLING_PARTY_ADDRESS
,
3264 dissect_sccp_variable_parameter(tvb
, pinfo
, sccp_tree
, tree
,
3265 PARAMETER_LONG_DATA
, variable_pointer3
);
3269 dissect_sccp_unknown_message(tvb
, sccp_tree
);
3273 dissect_sccp_optional_parameters(tvb
, pinfo
, sccp_tree
, tree
,
3276 if (trace_sccp
&& assoc
&& (assoc
!= &no_assoc
)) {
3277 proto_item
*pi
= proto_tree_add_uint(sccp_tree
, hf_sccp_assoc_id
, tvb
, 0, 0, assoc
->id
);
3278 proto_tree
*pt
= proto_item_add_subtree(pi
, ett_sccp_assoc
);
3279 PROTO_ITEM_SET_GENERATED(pi
);
3282 for(m
= assoc
->msgs
; m
; m
= m
->data
.co
.next
) {
3283 pi
= proto_tree_add_uint(pt
, hf_sccp_assoc_msg
, tvb
, 0, 0, m
->framenum
);
3285 if (assoc
->payload
!= SCCP_PLOAD_NONE
)
3286 proto_item_append_text(pi
," %s", val_to_str(assoc
->payload
, assoc_protos
, "Unknown: %d"));
3288 if (m
->data
.co
.label
)
3289 proto_item_append_text(pi
," %s", m
->data
.co
.label
);
3291 if ((m
->framenum
== PINFO_FD_NUM(pinfo
)) && (m
->offset
== msg_offset
) ) {
3292 tap_queue_packet(sccp_tap
, pinfo
, m
);
3293 proto_item_append_text(pi
," (current)");
3295 PROTO_ITEM_SET_GENERATED(pi
);
3304 dissect_sccp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
3306 proto_item
*sccp_item
= NULL
;
3307 proto_tree
*sccp_tree
= NULL
;
3308 const mtp3_addr_pc_t
*mtp3_addr_p
;
3310 if ((pinfo
->src
.type
== AT_SS7PC
) &&
3311 ((mtp3_addr_p
= (const mtp3_addr_pc_t
*)pinfo
->src
.data
)->type
<= CHINESE_ITU_STANDARD
)) {
3313 * Allow a protocol beneath to specify how the SCCP layer should be
3316 * It is possible to have multiple sets of SCCP traffic some of which is
3317 * ITU and some of which is ANSI.
3318 * An example is A-interface traffic having ANSI MTP3/ANSI SCCP/3GPP2 IOS
3319 * and at the same time ITU MTP3/ITU SCCP/ANSI TCAP/ANSI MAP.
3321 decode_mtp3_standard
= mtp3_addr_p
->type
;
3323 decode_mtp3_standard
= (Standard_Type
)mtp3_standard
;
3326 /* Make entry in the Protocol column on summary display */
3327 switch (decode_mtp3_standard
) {
3329 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SCCP (Int. ITU)");
3332 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SCCP (ANSI)");
3334 case CHINESE_ITU_STANDARD
:
3335 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SCCP (Chin. ITU)");
3337 case JAPAN_STANDARD
:
3338 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SCCP (Japan)");
3342 /* In the interest of speed, if "tree" is NULL, don't do any work not
3343 necessary to generate protocol tree items. */
3345 /* create the sccp protocol tree */
3346 sccp_item
= proto_tree_add_item(tree
, proto_sccp
, tvb
, 0, -1, ENC_NA
);
3347 sccp_tree
= proto_item_add_subtree(sccp_item
, ett_sccp
);
3350 /* Set whether message is UPLINK, DOWNLINK, or of UNKNOWN direction */
3352 if (pinfo
->src
.type
== AT_SS7PC
) {
3354 * XXX - we assume that the "data" pointers of the source and destination
3355 * addresses are set to point to "mtp3_addr_pc_t" structures, so that
3356 * we can safely cast them.
3358 mtp3_addr_p
= (const mtp3_addr_pc_t
*)pinfo
->src
.data
;
3360 if (sccp_source_pc_global
== mtp3_addr_p
->pc
) {
3361 pinfo
->p2p_dir
= P2P_DIR_SENT
;
3363 /* assuming if src was SS7 PC then dst will be too */
3364 mtp3_addr_p
= (const mtp3_addr_pc_t
*)pinfo
->dst
.data
;
3366 if (sccp_source_pc_global
== mtp3_addr_p
->pc
)
3368 pinfo
->p2p_dir
= P2P_DIR_RECV
;
3370 pinfo
->p2p_dir
= P2P_DIR_UNKNOWN
;
3375 /* dissect the message */
3376 dissect_sccp_message(tvb
, pinfo
, sccp_tree
, tree
);
3380 /*** SccpUsers Table **/
3382 static struct _sccp_ul
{
3385 dissector_handle_t
*handlep
;
3388 {SCCP_USER_DATA
, FALSE
, &data_handle
},
3389 {SCCP_USER_TCAP
, FALSE
, &tcap_handle
},
3390 {SCCP_USER_RANAP
, FALSE
, &ranap_handle
},
3391 {SCCP_USER_BSSAP
, FALSE
, &bssap_handle
},
3392 {SCCP_USER_GSMMAP
, TRUE
, &gsmmap_handle
},
3393 {SCCP_USER_CAMEL
, TRUE
, &camel_handle
},
3394 {SCCP_USER_INAP
, TRUE
, &inap_handle
},
3399 sccp_users_update_cb(void *r
, const char **err
)
3401 sccp_user_t
*u
= (sccp_user_t
*)r
;
3405 empty
= range_empty();
3406 if (ranges_are_equal(u
->called_pc
, empty
)) {
3407 *err
= g_strdup("Must specify a PC");
3411 if (ranges_are_equal(u
->called_ssn
, empty
)) {
3412 *err
= g_strdup("Must specify an SSN");
3416 for (c
=user_list
; c
->handlep
; c
++) {
3417 if (c
->id
== u
->user
) {
3418 u
->uses_tcap
= c
->uses_tcap
;
3419 u
->handlep
= c
->handlep
;
3424 u
->uses_tcap
= FALSE
;
3425 u
->handlep
= &data_handle
;
3429 sccp_users_copy_cb(void *n
, const void *o
, size_t siz _U_
)
3431 const sccp_user_t
*u
= (const sccp_user_t
*)o
;
3432 sccp_user_t
*un
= (sccp_user_t
*)n
;
3436 un
->uses_tcap
= u
->uses_tcap
;
3437 un
->handlep
= u
->handlep
;
3440 un
->called_pc
= range_copy(u
->called_pc
);
3442 un
->called_ssn
= range_copy(u
->called_ssn
);
3448 sccp_users_free_cb(void *r
)
3450 sccp_user_t
*u
= (sccp_user_t
*)r
;
3451 if (u
->called_pc
) g_free(u
->called_pc
);
3452 if (u
->called_ssn
) g_free(u
->called_ssn
);
3456 UAT_DEC_CB_DEF(sccp_users
, ni
, sccp_user_t
)
3457 UAT_RANGE_CB_DEF(sccp_users
, called_pc
, sccp_user_t
)
3458 UAT_RANGE_CB_DEF(sccp_users
, called_ssn
, sccp_user_t
)
3459 UAT_VS_DEF(sccp_users
, user
, sccp_user_t
, guint
, SCCP_USER_DATA
, "Data")
3461 /** End SccpUsersTable **/
3468 reassembly_table_init (&sccp_xudt_msg_reassembly_table
,
3469 &addresses_reassembly_table_functions
);
3472 /* Register the protocol with Wireshark */
3474 proto_register_sccp(void)
3476 /* Setup list of header fields */
3477 static hf_register_info hf
[] = {
3478 { &hf_sccp_message_type
,
3479 { "Message Type", "sccp.message_type",
3480 FT_UINT8
, BASE_HEX
, VALS(sccp_message_type_values
), 0x0,
3483 { &hf_sccp_variable_pointer1
,
3484 { "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1",
3485 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3488 { &hf_sccp_variable_pointer2
,
3489 { "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2",
3490 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3493 { &hf_sccp_variable_pointer3
,
3494 { "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3",
3495 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3498 { &hf_sccp_optional_pointer
,
3499 { "Pointer to Optional parameter", "sccp.optional_pointer",
3500 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3503 { &hf_sccp_param_length
,
3504 { "Variable parameter length", "sccp.parameter_length",
3505 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3509 { "Called or Calling SubSystem Number", "sccp.ssn",
3510 FT_UINT8
, BASE_DEC
, VALS(sccp_ssn_values
), 0x0,
3513 { &hf_sccp_gt_digits
,
3514 { "Called or Calling GT Digits", "sccp.digits",
3515 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3518 { &hf_sccp_called_ansi_national_indicator
,
3519 { "National Indicator", "sccp.called.ni",
3520 FT_UINT8
, BASE_HEX
, VALS(sccp_ansi_national_indicator_values
), ANSI_NATIONAL_MASK
,
3523 { &hf_sccp_called_itu_natl_use_bit
,
3524 { "Reserved for national use", "sccp.called.reserved",
3525 FT_UINT8
, BASE_HEX
, NULL
, ITU_RESERVED_MASK
,
3528 { &hf_sccp_called_routing_indicator
,
3529 { "Routing Indicator", "sccp.called.ri",
3530 FT_UINT8
, BASE_HEX
, VALS(sccp_routing_indicator_values
), ROUTING_INDICATOR_MASK
,
3533 { &hf_sccp_called_itu_global_title_indicator
,
3534 { "Global Title Indicator", "sccp.called.gti",
3535 FT_UINT8
, BASE_HEX
, VALS(sccp_itu_global_title_indicator_values
), GTI_MASK
,
3538 { &hf_sccp_called_ansi_global_title_indicator
,
3539 { "Global Title Indicator", "sccp.called.gti",
3540 FT_UINT8
, BASE_HEX
, VALS(sccp_ansi_global_title_indicator_values
), GTI_MASK
,
3543 { &hf_sccp_called_itu_ssn_indicator
,
3544 { "SubSystem Number Indicator", "sccp.called.ssni",
3545 FT_UINT8
, BASE_HEX
, VALS(sccp_ai_ssni_values
), ITU_SSN_INDICATOR_MASK
,
3548 { &hf_sccp_called_itu_point_code_indicator
,
3549 { "Point Code Indicator", "sccp.called.pci",
3550 FT_UINT8
, BASE_HEX
, VALS(sccp_ai_pci_values
), ITU_PC_INDICATOR_MASK
,
3553 { &hf_sccp_called_ansi_ssn_indicator
,
3554 { "SubSystem Number Indicator", "sccp.called.ssni",
3555 FT_UINT8
, BASE_HEX
, VALS(sccp_ai_ssni_values
), ANSI_SSN_INDICATOR_MASK
,
3558 { &hf_sccp_called_ansi_point_code_indicator
,
3559 { "Point Code Indicator", "sccp.called.pci",
3560 FT_UINT8
, BASE_HEX
, VALS(sccp_ai_pci_values
), ANSI_PC_INDICATOR_MASK
,
3563 { &hf_sccp_called_ssn
,
3564 { "SubSystem Number", "sccp.called.ssn",
3565 FT_UINT8
, BASE_DEC
, VALS(sccp_ssn_values
), 0x0,
3568 { &hf_sccp_called_itu_pc
,
3569 { "PC", "sccp.called.pc",
3570 FT_UINT16
, BASE_DEC
, NULL
, ITU_PC_MASK
,
3573 { &hf_sccp_called_ansi_pc
,
3574 { "PC", "sccp.called.ansi_pc",
3575 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3578 { &hf_sccp_called_chinese_pc
,
3579 { "PC", "sccp.called.chinese_pc",
3580 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3583 { &hf_sccp_called_japan_pc
,
3584 { "PC", "sccp.called.pc",
3585 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3588 { &hf_sccp_called_pc_network
,
3589 { "PC Network", "sccp.called.network",
3590 FT_UINT24
, BASE_DEC
, NULL
, ANSI_NETWORK_MASK
,
3593 { &hf_sccp_called_pc_cluster
,
3594 { "PC Cluster", "sccp.called.cluster",
3595 FT_UINT24
, BASE_DEC
, NULL
, ANSI_CLUSTER_MASK
,
3598 { &hf_sccp_called_pc_member
,
3599 { "PC Member", "sccp.called.member",
3600 FT_UINT24
, BASE_DEC
, NULL
, ANSI_MEMBER_MASK
,
3603 { &hf_sccp_called_gt_nai
,
3604 { "Nature of Address Indicator", "sccp.called.nai",
3605 FT_UINT8
, BASE_HEX
, VALS(sccp_nai_values
), GT_NAI_MASK
,
3608 { &hf_sccp_called_gt_oe
,
3609 { "Odd/Even Indicator", "sccp.called.oe",
3610 FT_UINT8
, BASE_HEX
, VALS(sccp_oe_values
), GT_OE_MASK
,
3613 { &hf_sccp_called_gt_tt
,
3614 { "Translation Type", "sccp.called.tt",
3615 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3618 { &hf_sccp_called_gt_np
,
3619 { "Numbering Plan", "sccp.called.np",
3620 FT_UINT8
, BASE_HEX
, VALS(sccp_np_values
), GT_NP_MASK
,
3623 { &hf_sccp_called_gt_es
,
3624 { "Encoding Scheme", "sccp.called.es",
3625 FT_UINT8
, BASE_HEX
, VALS(sccp_es_values
), GT_ES_MASK
,
3628 { &hf_sccp_called_gt_digits
,
3629 { "Called Party Digits", "sccp.called.digits",
3630 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3633 { &hf_sccp_called_gt_digits_length
,
3634 { "Number of Called Party Digits", "sccp.called.digits.length",
3635 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3638 { &hf_sccp_calling_ansi_national_indicator
,
3639 { "National Indicator", "sccp.calling.ni",
3640 FT_UINT8
, BASE_HEX
, VALS(sccp_ansi_national_indicator_values
), ANSI_NATIONAL_MASK
,
3643 { &hf_sccp_calling_itu_natl_use_bit
,
3644 { "Reserved for national use", "sccp.calling.reserved",
3645 FT_UINT8
, BASE_HEX
, NULL
, ITU_RESERVED_MASK
,
3648 { &hf_sccp_calling_routing_indicator
,
3649 { "Routing Indicator", "sccp.calling.ri",
3650 FT_UINT8
, BASE_HEX
, VALS(sccp_routing_indicator_values
), ROUTING_INDICATOR_MASK
,
3653 { &hf_sccp_calling_itu_global_title_indicator
,
3654 { "Global Title Indicator", "sccp.calling.gti",
3655 FT_UINT8
, BASE_HEX
, VALS(sccp_itu_global_title_indicator_values
), GTI_MASK
,
3658 { &hf_sccp_calling_ansi_global_title_indicator
,
3659 { "Global Title Indicator", "sccp.calling.gti",
3660 FT_UINT8
, BASE_HEX
, VALS(sccp_ansi_global_title_indicator_values
), GTI_MASK
,
3663 { &hf_sccp_calling_itu_ssn_indicator
,
3664 { "SubSystem Number Indicator", "sccp.calling.ssni",
3665 FT_UINT8
, BASE_HEX
, VALS(sccp_ai_ssni_values
), ITU_SSN_INDICATOR_MASK
,
3668 { &hf_sccp_calling_itu_point_code_indicator
,
3669 { "Point Code Indicator", "sccp.calling.pci",
3670 FT_UINT8
, BASE_HEX
, VALS(sccp_ai_pci_values
), ITU_PC_INDICATOR_MASK
,
3673 { &hf_sccp_calling_ansi_ssn_indicator
,
3674 { "SubSystem Number Indicator", "sccp.calling.ssni",
3675 FT_UINT8
, BASE_HEX
, VALS(sccp_ai_ssni_values
), ANSI_SSN_INDICATOR_MASK
,
3678 { &hf_sccp_calling_ansi_point_code_indicator
,
3679 { "Point Code Indicator", "sccp.calling.pci",
3680 FT_UINT8
, BASE_HEX
, VALS(sccp_ai_pci_values
), ANSI_PC_INDICATOR_MASK
,
3683 { &hf_sccp_calling_ssn
,
3684 { "SubSystem Number", "sccp.calling.ssn",
3685 FT_UINT8
, BASE_DEC
, VALS(sccp_ssn_values
), 0x0,
3688 { &hf_sccp_calling_itu_pc
,
3689 { "PC", "sccp.calling.pc",
3690 FT_UINT16
, BASE_DEC
, NULL
, ITU_PC_MASK
,
3693 { &hf_sccp_calling_ansi_pc
,
3694 { "PC", "sccp.calling.ansi_pc",
3695 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3698 { &hf_sccp_calling_chinese_pc
,
3699 { "PC", "sccp.calling.chinese_pc",
3700 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3703 { &hf_sccp_calling_japan_pc
,
3704 { "PC", "sccp.calling.pc",
3705 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3708 { &hf_sccp_calling_pc_network
,
3709 { "PC Network", "sccp.calling.network",
3710 FT_UINT24
, BASE_DEC
, NULL
, ANSI_NETWORK_MASK
,
3713 { &hf_sccp_calling_pc_cluster
,
3714 { "PC Cluster", "sccp.calling.cluster",
3715 FT_UINT24
, BASE_DEC
, NULL
, ANSI_CLUSTER_MASK
,
3718 { &hf_sccp_calling_pc_member
,
3719 { "PC Member", "sccp.calling.member",
3720 FT_UINT24
, BASE_DEC
, NULL
, ANSI_MEMBER_MASK
,
3723 { &hf_sccp_calling_gt_nai
,
3724 { "Nature of Address Indicator", "sccp.calling.nai",
3725 FT_UINT8
, BASE_HEX
, VALS(sccp_nai_values
), GT_NAI_MASK
,
3728 { &hf_sccp_calling_gt_oe
,
3729 { "Odd/Even Indicator", "sccp.calling.oe",
3730 FT_UINT8
, BASE_HEX
, VALS(sccp_oe_values
), GT_OE_MASK
,
3733 { &hf_sccp_calling_gt_tt
,
3734 { "Translation Type", "sccp.calling.tt",
3735 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3738 { &hf_sccp_calling_gt_np
,
3739 { "Numbering Plan", "sccp.calling.np",
3740 FT_UINT8
, BASE_HEX
, VALS(sccp_np_values
), GT_NP_MASK
,
3743 { &hf_sccp_calling_gt_es
,
3744 { "Encoding Scheme", "sccp.calling.es",
3745 FT_UINT8
, BASE_HEX
, VALS(sccp_es_values
), GT_ES_MASK
,
3748 { &hf_sccp_calling_gt_digits
,
3749 { "Calling Party Digits", "sccp.calling.digits",
3750 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3753 { &hf_sccp_calling_gt_digits_length
,
3754 { "Number of Calling Party Digits", "sccp.calling.digits.length",
3755 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3759 { "Destination Local Reference", "sccp.dlr",
3760 FT_UINT24
, BASE_HEX
, NULL
, 0x0,
3764 { "Source Local Reference", "sccp.slr",
3765 FT_UINT24
, BASE_HEX
, NULL
, 0x0,
3769 { "Local Reference", "sccp.lr",
3770 FT_UINT24
, BASE_HEX
, NULL
, 0x0,
3774 { "Class", "sccp.class",
3775 FT_UINT8
, BASE_HEX
, NULL
, CLASS_CLASS_MASK
,
3778 { &hf_sccp_handling
,
3779 { "Message handling", "sccp.handling",
3780 FT_UINT8
, BASE_HEX
, VALS(sccp_class_handling_values
), CLASS_SPARE_HANDLING_MASK
,
3784 { "More data", "sccp.more",
3785 FT_UINT8
, BASE_HEX
, VALS(sccp_segmenting_reassembling_values
), SEGMENTING_REASSEMBLING_MASK
,
3789 { "Receive Sequence Number", "sccp.rsn",
3790 FT_UINT8
, BASE_HEX
, NULL
, RSN_MASK
,
3793 { &hf_sccp_sequencing_segmenting_ssn
,
3794 { "Sequencing Segmenting: Send Sequence Number", "sccp.sequencing_segmenting.ssn",
3795 FT_UINT8
, BASE_HEX
, NULL
, SEND_SEQUENCE_NUMBER_MASK
,
3798 { &hf_sccp_sequencing_segmenting_rsn
,
3799 { "Sequencing Segmenting: Receive Sequence Number", "sccp.sequencing_segmenting.rsn",
3800 FT_UINT8
, BASE_HEX
, NULL
, RECEIVE_SEQUENCE_NUMBER_MASK
,
3803 { &hf_sccp_sequencing_segmenting_more
,
3804 { "Sequencing Segmenting: More", "sccp.sequencing_segmenting.more",
3805 FT_UINT8
, BASE_HEX
, VALS(sccp_segmenting_reassembling_values
), SEQUENCING_SEGMENTING_MORE_MASK
,
3809 { "Credit", "sccp.credit",
3810 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3813 { &hf_sccp_release_cause
,
3814 { "Release Cause", "sccp.release_cause",
3815 FT_UINT8
, BASE_HEX
, VALS(sccp_release_cause_values
), 0x0,
3818 { &hf_sccp_return_cause
,
3819 { "Return Cause", "sccp.return_cause",
3820 FT_UINT8
, BASE_HEX
, VALS(sccp_return_cause_values
), 0x0,
3823 { &hf_sccp_reset_cause
,
3824 { "Reset Cause", "sccp.reset_cause",
3825 FT_UINT8
, BASE_HEX
, VALS(sccp_reset_cause_values
), 0x0,
3828 { &hf_sccp_error_cause
,
3829 { "Error Cause", "sccp.error_cause",
3830 FT_UINT8
, BASE_HEX
, VALS(sccp_error_cause_values
), 0x0,
3833 { &hf_sccp_refusal_cause
,
3834 { "Refusal Cause", "sccp.refusal_cause",
3835 FT_UINT8
, BASE_HEX
, VALS(sccp_refusal_cause_values
), 0x0,
3838 { &hf_sccp_segmentation_first
,
3839 { "Segmentation: First", "sccp.segmentation.first",
3840 FT_UINT8
, BASE_HEX
, VALS(sccp_segmentation_first_segment_values
), SEGMENTATION_FIRST_SEGMENT_MASK
,
3843 { &hf_sccp_segmentation_class
,
3844 { "Segmentation: Class", "sccp.segmentation.class",
3845 FT_UINT8
, BASE_HEX
, VALS(sccp_segmentation_class_values
), SEGMENTATION_CLASS_MASK
,
3848 { &hf_sccp_segmentation_remaining
,
3849 { "Segmentation: Remaining", "sccp.segmentation.remaining",
3850 FT_UINT8
, BASE_HEX
, NULL
, SEGMENTATION_REMAINING_MASK
,
3853 { &hf_sccp_segmentation_slr
,
3854 { "Segmentation: Source Local Reference", "sccp.segmentation.slr",
3855 FT_UINT24
, BASE_HEX
, NULL
, 0x0,
3858 { &hf_sccp_hop_counter
,
3859 { "Hop Counter", "sccp.hops",
3860 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3863 { &hf_sccp_importance
,
3864 { "Importance", "sccp.importance",
3865 FT_UINT8
, BASE_HEX
, NULL
, IMPORTANCE_IMPORTANCE_MASK
,
3868 /* ISNI is ANSI only */
3869 { &hf_sccp_ansi_isni_mi
,
3870 { "ISNI Mark for Identification Indicator", "sccp.isni.mi",
3871 FT_UINT8
, BASE_HEX
, VALS(sccp_isni_mark_for_id_values
), ANSI_ISNI_MI_MASK
,
3874 { &hf_sccp_ansi_isni_iri
,
3875 { "ISNI Routing Indicator", "sccp.isni.iri",
3876 FT_UINT8
, BASE_HEX
, VALS(sccp_isni_iri_values
), ANSI_ISNI_IRI_MASK
,
3879 { &hf_sccp_ansi_isni_ti
,
3880 { "ISNI Type Indicator", "sccp.isni.ti",
3881 FT_UINT8
, BASE_HEX
, VALS(sccp_isni_ti_values
), ANSI_ISNI_TI_MASK
,
3884 { &hf_sccp_ansi_isni_netspec
,
3885 { "ISNI Network Specific (Type 1)", "sccp.isni.netspec",
3886 FT_UINT8
, BASE_HEX
, NULL
, ANSI_ISNI_NETSPEC_MASK
,
3889 { &hf_sccp_ansi_isni_counter
,
3890 { "ISNI Counter", "sccp.isni.counter",
3891 FT_UINT8
, BASE_DEC
, NULL
, ANSI_ISNI_COUNTER_MASK
,
3894 { &hf_sccp_ansi_isni_network
,
3895 { "Network ID network", "sccp.isni.network",
3896 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3899 { &hf_sccp_ansi_isni_cluster
,
3900 { "Network ID cluster", "sccp.isni.cluster",
3901 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3904 {&hf_sccp_xudt_msg_fragments
,
3905 { "Message fragments", "sccp.msg.fragments",
3906 FT_NONE
, BASE_NONE
, NULL
, 0x00,
3909 {&hf_sccp_xudt_msg_fragment
,
3910 { "Message fragment", "sccp.msg.fragment",
3911 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
3914 {&hf_sccp_xudt_msg_fragment_overlap
,
3915 { "Message fragment overlap", "sccp.msg.fragment.overlap",
3916 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3919 {&hf_sccp_xudt_msg_fragment_overlap_conflicts
,
3920 { "Message fragment overlapping with conflicting data", "sccp.msg.fragment.overlap.conflicts",
3921 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3924 {&hf_sccp_xudt_msg_fragment_multiple_tails
,
3925 { "Message has multiple tail fragments", "sccp.msg.fragment.multiple_tails",
3926 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3929 {&hf_sccp_xudt_msg_fragment_too_long_fragment
,
3930 { "Message fragment too long", "sccp.msg.fragment.too_long_fragment",
3931 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3934 {&hf_sccp_xudt_msg_fragment_error
,
3935 { "Message defragmentation error", "sccp.msg.fragment.error",
3936 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
3939 {&hf_sccp_xudt_msg_fragment_count
,
3940 { "Message fragment count", "sccp.msg.fragment.count",
3941 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
3944 {&hf_sccp_xudt_msg_reassembled_in
,
3945 { "Reassembled in", "sccp.msg.reassembled.in",
3946 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
3949 {&hf_sccp_xudt_msg_reassembled_length
,
3950 { "Reassembled SCCP length", "sccp.msg.reassembled.length",
3951 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
3954 { &hf_sccp_assoc_id
,
3955 { "Association ID", "sccp.assoc.id",
3956 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3959 {&hf_sccp_assoc_msg
,
3960 { "Message in frame", "sccp.assoc.msg",
3961 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
3966 /* Setup protocol subtree array */
3967 static gint
*ett
[] = {
3970 &ett_sccp_called_ai
,
3971 &ett_sccp_called_pc
,
3972 &ett_sccp_called_gt
,
3973 &ett_sccp_called_gt_digits
,
3975 &ett_sccp_calling_ai
,
3976 &ett_sccp_calling_pc
,
3977 &ett_sccp_calling_gt
,
3978 &ett_sccp_calling_gt_digits
,
3979 &ett_sccp_sequencing_segmenting
,
3980 &ett_sccp_segmentation
,
3981 &ett_sccp_ansi_isni_routing_control
,
3982 &ett_sccp_xudt_msg_fragment
,
3983 &ett_sccp_xudt_msg_fragments
,
3987 static ei_register_info ei
[] = {
3988 { &ei_sccp_wrong_length
, { "sccp.wrong_length", PI_MALFORMED
, PI_ERROR
, "Wrong length indicated.", EXPFILL
}},
3989 { &ei_sccp_international_standard_address
, { "sccp.international_standard_address", PI_MALFORMED
, PI_WARN
,
3990 "Address is coded to international standards. This doesn't normally happen in ANSI networks.", EXPFILL
}},
3991 { &ei_sccp_no_ssn_present
, { "sccp.ssn.not_present", PI_PROTOCOL
, PI_WARN
, "Message is routed on SSN, but SSN is not present", EXPFILL
}},
3992 { &ei_sccp_ssn_zero
, { "sccp.ssn.is_zero", PI_PROTOCOL
, PI_WARN
, "Message is routed on SSN, but SSN is zero (unspecified)", EXPFILL
}},
3993 { &ei_sccp_class_unexpected
, { "sccp.class_unexpected", PI_MALFORMED
, PI_ERROR
, "Unexpected message class for this message type", EXPFILL
}},
3994 { &ei_sccp_handling_invalid
, { "sccp.handling_invalid", PI_MALFORMED
, PI_ERROR
, "Invalid message handling", EXPFILL
}},
3997 module_t
*sccp_module
;
3998 expert_module_t
* expert_sccp
;
4000 static uat_field_t users_flds
[] = {
4001 UAT_FLD_DEC(sccp_users
, ni
, "Network Indicator", "Network Indicator"),
4002 UAT_FLD_RANGE(sccp_users
, called_pc
, "Called DPCs", 0xFFFFFF, "DPCs for which this protocol is to be used"),
4003 UAT_FLD_RANGE(sccp_users
, called_ssn
, "Called SSNs", 255, "Called SSNs for which this protocol is to be used"),
4004 UAT_FLD_VS(sccp_users
, user
, "User protocol", sccp_users_vals
, "The User Protocol"),
4009 uat_t
*users_uat
= uat_new("SCCP Users Table", sizeof(sccp_user_t
),
4010 "sccp_users", TRUE
, (void**) &sccp_users
,
4011 &num_sccp_users
, UAT_AFFECTS_DISSECTION
,
4012 "ChSccpUsers", sccp_users_copy_cb
,
4013 sccp_users_update_cb
, sccp_users_free_cb
,
4016 /* Register the protocol name and description */
4017 proto_sccp
= proto_register_protocol("Signalling Connection Control Part",
4020 register_dissector("sccp", dissect_sccp
, proto_sccp
);
4022 /* Required function calls to register the header fields and subtrees used */
4023 proto_register_field_array(proto_sccp
, hf
, array_length(hf
));
4024 proto_register_subtree_array(ett
, array_length(ett
));
4025 expert_sccp
= expert_register_protocol(proto_sccp
);
4026 expert_register_field_array(expert_sccp
, ei
, array_length(ei
));
4028 sccp_ssn_dissector_table
= register_dissector_table("sccp.ssn", "SCCP SSN", FT_UINT8
, BASE_DEC
);
4030 register_heur_dissector_list("sccp", &heur_subdissector_list
);
4032 sccp_module
= prefs_register_protocol(proto_sccp
, proto_reg_handoff_sccp
);
4034 prefs_register_uint_preference(sccp_module
, "source_pc",
4035 "Source PC (in hex)",
4036 "The source point code (usually MSC) (to determine whether message is uplink or downlink)",
4037 16, &sccp_source_pc_global
);
4039 prefs_register_bool_preference(sccp_module
, "show_length", "Show length",
4040 "Show parameter length in the protocol tree",
4043 prefs_register_bool_preference(sccp_module
, "defragment_xudt",
4044 "Reassemble XUDT messages",
4045 "Whether XUDT messages should be reassembled",
4046 &sccp_xudt_desegment
);
4048 prefs_register_bool_preference(sccp_module
, "trace_sccp",
4049 "Trace Associations",
4050 "Whether to keep information about messages and their associations",
4054 prefs_register_bool_preference(sccp_module
, "show_more_info",
4055 "Show key parameters in Info Column",
4056 "Show SLR, DLR, and CAUSE Parameters in the Information Column of the Summary",
4060 prefs_register_uat_preference(sccp_module
, "users_table", "Users Table",
4061 "A table that enumerates user protocols to be used against specific PCs and SSNs",
4064 prefs_register_bool_preference(sccp_module
, "set_addresses", "Set source and destination GT addresses",
4065 "Set the source and destination addresses to the GT digits (if RI=GT)."
4066 " This may affect TCAP's ability to recognize which messages belong to which TCAP session.",
4069 prefs_register_string_preference(sccp_module
, "default_payload", "Default Payload",
4070 "The protocol which should be used to dissect the payload if nothing else has claimed it",
4073 register_init_routine(&init_sccp
);
4075 assocs
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
4077 sccp_tap
= register_tap("sccp");
4082 proto_reg_handoff_sccp(void)
4084 dissector_handle_t sccp_handle
;
4086 static gboolean initialised
= FALSE
;
4089 sccp_handle
= find_dissector("sccp");
4091 dissector_add_uint("wtap_encap", WTAP_ENCAP_SCCP
, sccp_handle
);
4092 dissector_add_uint("mtp3.service_indicator", MTP_SI_SCCP
, sccp_handle
);
4093 dissector_add_string("tali.opcode", "sccp", sccp_handle
);
4095 data_handle
= find_dissector("data");
4096 tcap_handle
= find_dissector("tcap");
4097 ranap_handle
= find_dissector("ranap");
4098 bssap_handle
= find_dissector("bssap");
4099 gsmmap_handle
= find_dissector("gsm_map");
4100 camel_handle
= find_dissector("camel");
4101 inap_handle
= find_dissector("inap");
4106 default_handle
= find_dissector(default_payload
);