2 * Routines for Signalling Connection Control Part (SCCP) dissection
4 * It is hopefully compliant to:
7 * YDN 038-1997 (Chinese ITU variant)
9 * Copyright 2002, Jeff Morriss <jeff.morriss[AT]ulticom.com>
11 * $Id: packet-sccp.c,v 1.11 2003/06/26 06:28:47 guy Exp $
13 * Ethereal - Network traffic analyzer
14 * By Gerald Combs <gerald@ethereal.com>
15 * Copyright 1998 Gerald Combs
17 * Copied from packet-m2pa.c
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
44 #ifdef NEED_SNPRINTF_H
48 #include <epan/packet.h>
49 #include "packet-mtp3.h"
53 #define MESSAGE_TYPE_OFFSET 0
54 #define MESSAGE_TYPE_LENGTH 1
55 #define POINTER_LENGTH 1
56 #define POINTER_LENGTH_LONG 2
58 #define MESSAGE_TYPE_CR 0x01
59 #define MESSAGE_TYPE_CC 0x02
60 #define MESSAGE_TYPE_CREF 0x03
61 #define MESSAGE_TYPE_RLSD 0x04
62 #define MESSAGE_TYPE_RLC 0x05
63 #define MESSAGE_TYPE_DT1 0x06
64 #define MESSAGE_TYPE_DT2 0x07
65 #define MESSAGE_TYPE_AK 0x08
66 #define MESSAGE_TYPE_UDT 0x09
67 #define MESSAGE_TYPE_UDTS 0x0a
68 #define MESSAGE_TYPE_ED 0x0b
69 #define MESSAGE_TYPE_EA 0x0c
70 #define MESSAGE_TYPE_RSR 0x0d
71 #define MESSAGE_TYPE_RSC 0x0e
72 #define MESSAGE_TYPE_ERR 0x0f
73 #define MESSAGE_TYPE_IT 0x10
74 #define MESSAGE_TYPE_XUDT 0x11
75 #define MESSAGE_TYPE_XUDTS 0x12
76 /* The below 2 are ITU only */
77 #define MESSAGE_TYPE_LUDT 0x13
78 #define MESSAGE_TYPE_LUDTS 0x14
80 /* Same as below but with names typed out */
81 static const value_string sccp_message_type_values[] = {
82 { MESSAGE_TYPE_CR, "Connection Request" },
83 { MESSAGE_TYPE_CC, "Connection Confirm" },
84 { MESSAGE_TYPE_CREF, "Connection Refused" },
85 { MESSAGE_TYPE_RLSD, "Released" },
86 { MESSAGE_TYPE_RLC, "Release Complete" },
87 { MESSAGE_TYPE_DT1, "Data Form 1" },
88 { MESSAGE_TYPE_DT2, "Data Form 2" },
89 { MESSAGE_TYPE_AK, "Data Acknowledgement" },
90 { MESSAGE_TYPE_UDT, "Unitdata" },
91 { MESSAGE_TYPE_UDTS, "Unitdata Service" },
92 { MESSAGE_TYPE_ED, "Expedited Data" },
93 { MESSAGE_TYPE_EA, "Expedited Data Acknowledgement" },
94 { MESSAGE_TYPE_RSR, "Reset Request" },
95 { MESSAGE_TYPE_RSC, "Reset Confirmation" },
96 { MESSAGE_TYPE_ERR, "Error" },
97 { MESSAGE_TYPE_IT, "Inactivity Timer" },
98 { MESSAGE_TYPE_XUDT, "Extended Unitdata" },
99 { MESSAGE_TYPE_XUDTS, "Extended Unitdata Service" },
100 { MESSAGE_TYPE_LUDT, "Long Unitdata (ITU)" },
101 { MESSAGE_TYPE_LUDTS, "Long Unitdata Service (ITU)" },
104 /* Same as above but in acronym form (for the Info column) */
105 static const value_string sccp_message_type_acro_values[] = {
106 { MESSAGE_TYPE_CR, "CR" },
107 { MESSAGE_TYPE_CC, "CC" },
108 { MESSAGE_TYPE_CREF, "CREF" },
109 { MESSAGE_TYPE_RLSD, "RLSD" },
110 { MESSAGE_TYPE_RLC, "RLC" },
111 { MESSAGE_TYPE_DT1, "DT1" },
112 { MESSAGE_TYPE_DT2, "DT2" },
113 { MESSAGE_TYPE_AK, "AK" },
114 { MESSAGE_TYPE_UDT, "UDT" },
115 { MESSAGE_TYPE_UDTS, "UDTS" },
116 { MESSAGE_TYPE_ED, "ED" },
117 { MESSAGE_TYPE_EA, "EA" },
118 { MESSAGE_TYPE_RSR, "RSR" },
119 { MESSAGE_TYPE_RSC, "RSC" },
120 { MESSAGE_TYPE_ERR, "ERR" },
121 { MESSAGE_TYPE_IT, "IT" },
122 { MESSAGE_TYPE_XUDT, "XUDT" },
123 { MESSAGE_TYPE_XUDTS, "XUDTS" },
124 { MESSAGE_TYPE_LUDT, "LUDT" },
125 { MESSAGE_TYPE_LUDTS, "LUDTS" },
128 #define PARAMETER_LENGTH_LENGTH 1
129 #define PARAMETER_LONG_DATA_LENGTH_LENGTH 2
130 #define PARAMETER_TYPE_LENGTH 1
132 #define PARAMETER_END_OF_OPTIONAL_PARAMETERS 0x00
133 #define PARAMETER_DESTINATION_LOCAL_REFERENCE 0x01
134 #define PARAMETER_SOURCE_LOCAL_REFERENCE 0x02
135 #define PARAMETER_CALLED_PARTY_ADDRESS 0x03
136 #define PARAMETER_CALLING_PARTY_ADDRESS 0x04
137 #define PARAMETER_CLASS 0x05
138 #define PARAMETER_SEGMENTING_REASSEMBLING 0x06
139 #define PARAMETER_RECEIVE_SEQUENCE_NUMBER 0x07
140 #define PARAMETER_SEQUENCING_SEGMENTING 0x08
141 #define PARAMETER_CREDIT 0x09
142 #define PARAMETER_RELEASE_CAUSE 0x0a
143 #define PARAMETER_RETURN_CAUSE 0x0b
144 #define PARAMETER_RESET_CAUSE 0x0c
145 #define PARAMETER_ERROR_CAUSE 0x0d
146 #define PARAMETER_REFUSAL_CAUSE 0x0e
147 #define PARAMETER_DATA 0x0f
148 #define PARAMETER_SEGMENTATION 0x10
149 #define PARAMETER_HOP_COUNTER 0x11
150 /* The below 2 are ITU only */
151 #define PARAMETER_IMPORTANCE 0x12
152 #define PARAMETER_LONG_DATA 0x13
153 /* ISNI is ANSI only */
154 #define PARAMETER_ISNI 0xfa
156 static const value_string sccp_parameter_values[] = {
157 { PARAMETER_END_OF_OPTIONAL_PARAMETERS, "End of Optional Parameters" },
158 { PARAMETER_DESTINATION_LOCAL_REFERENCE, "Destination Local Reference" },
159 { PARAMETER_SOURCE_LOCAL_REFERENCE, "Source Local Reference" },
160 { PARAMETER_CALLED_PARTY_ADDRESS, "Called Party Address" },
161 { PARAMETER_CALLING_PARTY_ADDRESS, "Calling Party Address" },
162 { PARAMETER_CLASS, "Protocol Class" },
163 { PARAMETER_SEGMENTING_REASSEMBLING, "Segmenting/Reassembling" },
164 { PARAMETER_RECEIVE_SEQUENCE_NUMBER, "Receive Sequence Number" },
165 { PARAMETER_SEQUENCING_SEGMENTING, "Sequencing/Segmenting" },
166 { PARAMETER_CREDIT, "Credit" },
167 { PARAMETER_RELEASE_CAUSE, "Release Cause" },
168 { PARAMETER_RETURN_CAUSE, "Return Cause" },
169 { PARAMETER_RESET_CAUSE, "Reset Cause" },
170 { PARAMETER_ERROR_CAUSE, "Error Cause" },
171 { PARAMETER_REFUSAL_CAUSE, "Refusal Cause" },
172 { PARAMETER_DATA, "Data" },
173 { PARAMETER_SEGMENTATION, "Segmentation" },
174 { PARAMETER_HOP_COUNTER, "Hop Counter" },
175 { PARAMETER_IMPORTANCE, "Importance (ITU)" },
176 { PARAMETER_LONG_DATA, "Long Data (ITU)" },
177 { PARAMETER_ISNI, "Intermediate Signaling Network Identification (ANSI)" },
181 #define END_OF_OPTIONAL_PARAMETERS_LENGTH 1
182 #define DESTINATION_LOCAL_REFERENCE_LENGTH 3
183 #define SOURCE_LOCAL_REFERENCE_LENGTH 3
184 #define PROTOCOL_CLASS_LENGTH 1
185 #define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
186 #define CREDIT_LENGTH 1
187 #define RELEASE_CAUSE_LENGTH 1
188 #define RETURN_CAUSE_LENGTH 1
189 #define RESET_CAUSE_LENGTH 1
190 #define ERROR_CAUSE_LENGTH 1
191 #define REFUSAL_CAUSE_LENGTH 1
192 #define HOP_COUNTER_LENGTH 1
193 #define IMPORTANCE_LENGTH 1
196 /* Parts of the Called and Calling Address parameters */
197 /* Address Indicator */
198 #define ADDRESS_INDICATOR_LENGTH 1
199 #define ITU_RESERVED_MASK 0x80
200 #define ANSI_NATIONAL_MASK 0x80
201 #define ROUTING_INDICATOR_MASK 0x40
202 #define GTI_MASK 0x3C
204 #define ITU_SSN_INDICATOR_MASK 0x02
205 #define ITU_PC_INDICATOR_MASK 0x01
206 #define ANSI_PC_INDICATOR_MASK 0x02
207 #define ANSI_SSN_INDICATOR_MASK 0x01
209 static const value_string sccp_national_indicator_values[] = {
210 { 0x0, "Address coded to International standard" },
211 { 0x1, "Address coded to National standard" },
214 static const value_string sccp_routing_indicator_values[] = {
215 { 0x0, "Route on GT" },
216 { 0x1, "Route on SSN" },
219 #define AI_GTI_NO_GT 0x0
220 #define ITU_AI_GTI_NAI 0x1
221 #define AI_GTI_TT 0x2
222 #define ITU_AI_GTI_TT_NP_ES 0x3
223 #define ITU_AI_GTI_TT_NP_ES_NAI 0x4
224 static const value_string sccp_itu_global_title_indicator_values[] = {
225 { AI_GTI_NO_GT, "No Global Title" },
226 { ITU_AI_GTI_NAI, "Nature of Address Indicator only" },
227 { AI_GTI_TT, "Translation Type only" },
228 { ITU_AI_GTI_TT_NP_ES, "Translation Type, Numbering Plan, and Encoding Scheme included" },
229 { ITU_AI_GTI_TT_NP_ES_NAI, "Translation Type, Numbering Plan, Encoding Scheme, and Nature of Address Indicator included" },
232 /* #define AI_GTI_NO_GT 0x0 */
233 #define ANSI_AI_GTI_TT_NP_ES 0x1
234 /* #define AI_GTI_TT 0x2 */
235 static const value_string sccp_ansi_global_title_indicator_values[] = {
236 { AI_GTI_NO_GT, "No Global Title" },
237 { ANSI_AI_GTI_TT_NP_ES, "Translation Type, Numbering Plan, and Encoding Scheme included" },
238 { AI_GTI_TT, "Translation Type only" },
241 static const value_string sccp_ai_pci_values[] = {
242 { 0x1, "Point Code present" },
243 { 0x0, "Point Code not present" },
246 static const value_string sccp_ai_ssni_values[] = {
247 { 0x1, "SSN present" },
248 { 0x0, "SSN not present" },
251 #define ADDRESS_SSN_LENGTH 1
252 #define INVALID_SSN 0xff
253 static const value_string sccp_ssn_values[] = {
254 { 0x00, "SSN not known/not used" },
255 { 0x01, "SCCP management" },
256 { 0x02, "Reserved for ITU-T allocation" },
257 { 0x03, "ISDN User Part" },
258 { 0x04, "OMAP (Operation, Maintenance, and Administration Part)" },
259 { 0x05, "MAP (Mobile Application Part)" },
260 { 0x06, "HLR (Home Location Register)" },
261 { 0x07, "VLR (Visitor Location Register)" },
262 { 0x08, "MSC (Mobile Switching Center)" },
263 { 0x09, "EIC/EIR (Equipment Identifier Center/Equipment Identification Register)" },
264 { 0x0a, "AUC/AC (Authentication Center)" },
265 { 0x0b, "ISDN supplementary services (ITU only)" },
266 { 0x0c, "Reserved for international use (ITU only)" },
267 { 0x0d, "Broadband ISDN edge-to-edge applications (ITU only)" },
268 { 0x0e, "TC test responder (ITU only)" },
272 /* * * * * * * * * * * * * * * * *
273 * Global Title: ITU GTI == 0001 *
274 * * * * * * * * * * * * * * * * */
275 #define GT_NAI_MASK 0x7F
276 #define GT_NAI_LENGTH 1
277 static const value_string sccp_nai_values[] = {
278 { 0x00, "NAI unknown" },
279 { 0x01, "Subscriber Number" },
280 { 0x02, "Reserved for national use" },
281 { 0x03, "National significant number" },
282 { 0x04, "International number" },
286 #define GT_OE_MASK 0x80
289 static const value_string sccp_oe_values[] = {
290 { GT_OE_EVEN, "Even number of address signals" },
291 { GT_OE_ODD, "Odd number of address signals" },
294 #define GT_SIGNAL_LENGTH 1
295 #define GT_ODD_SIGNAL_MASK 0x0f
296 #define GT_EVEN_SIGNAL_MASK 0xf0
297 #define GT_EVEN_SIGNAL_SHIFT 4
298 #define GT_MAX_SIGNALS 32
299 static const value_string sccp_address_signal_values[] = {
319 /* * * * * * * * * * * * * * * * * * * * *
320 * Global Title: ITU and ANSI GTI == 0010 *
321 * * * * * * * * * * * * * * * * * * * * */
322 #define GT_TT_LENGTH 1
325 /* * * * * * * * * * * * * * * * * * * * * * * * * *
326 * Global Title: ITU GTI == 0011, ANSI GTI == 0001 *
327 * * * * * * * * * * * * * * * * * * * * * * * * * */
328 #define GT_NP_MASK 0xf0
329 #define GT_NP_ES_LENGTH 1
330 static const value_string sccp_np_values[] = {
332 { 0x1, "ISDN/telephony" },
333 { 0x2, "Generic (ITU)/Reserved (ANSI)" },
336 { 0x5, "Maritime mobile" },
337 { 0x6, "Land mobile" },
338 { 0x7, "ISDN/mobile" },
339 { 0xe, "Private network or network-specific" },
343 #define GT_ES_MASK 0x0f
344 #define GT_ES_UNKNOWN 0x0
345 #define GT_ES_BCD_ODD 0x1
346 #define GT_ES_BCD_EVEN 0x2
347 #define GT_ES_NATIONAL 0x3
348 #define GT_ES_RESERVED 0xf
349 static const value_string sccp_es_values[] = {
350 { GT_ES_UNKNOWN, "Unknown" },
351 { GT_ES_BCD_ODD, "BCD, odd number of digits" },
352 { GT_ES_BCD_EVEN, "BCD, even number of digits" },
353 { GT_ES_NATIONAL, "National specific" },
354 { GT_ES_RESERVED, "Reserved (ITU)/Spare (ANSI)" },
357 /* Address signals above */
360 /* * * * * * * * * * * * * * * * *
361 * Global Title: ITU GTI == 0100 *
362 * * * * * * * * * * * * * * * * */
366 /* Address signals above */
369 #define CLASS_CLASS_MASK 0xf
370 #define CLASS_SPARE_HANDLING_MASK 0xf0
371 static const value_string sccp_class_handling_values [] = {
372 { 0x0, "No special options" },
373 { 0x8, "Return message on error" },
377 #define SEGMENTING_REASSEMBLING_LENGTH 1
378 #define SEGMENTING_REASSEMBLING_MASK 0x01
379 #define NO_MORE_DATA 0
381 /* This is also used by sequencing-segmenting parameter */
382 static const value_string sccp_segmenting_reassembling_values [] = {
383 { NO_MORE_DATA, "No more data" },
384 { MORE_DATA, "More data" },
388 #define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
389 #define RSN_MASK 0xfe
391 #define SEQUENCING_SEGMENTING_LENGTH 2
392 #define SEQUENCING_SEGMENTING_SSN_LENGTH 1
393 #define SEQUENCING_SEGMENTING_RSN_LENGTH 1
394 #define SEND_SEQUENCE_NUMBER_MASK 0xfe
395 #define RECEIVE_SEQUENCE_NUMBER_MASK 0xfe
396 #define SEQUENCING_SEGMENTING_MORE_MASK 0x01
399 #define CREDIT_LENGTH 1
401 #define RELEASE_CAUSE_LENGTH 1
402 static const value_string sccp_release_cause_values [] = {
403 { 0x00, "End user originated" },
404 { 0x01, "End user congestion" },
405 { 0x02, "End user failure" },
406 { 0x03, "SCCP user originated" },
407 { 0x04, "Remote procedure error" },
408 { 0x05, "Inconsistent connection data" },
409 { 0x06, "Access failure" },
410 { 0x07, "Access congestion" },
411 { 0x08, "Subsystem failure" },
412 { 0x09, "Subsystem congestion" },
413 { 0x0a, "MTP failure" },
414 { 0x0b, "Netowrk congestion" },
415 { 0x0c, "Expiration of reset timer" },
416 { 0x0d, "Expiration of receive inactivity timer" },
417 { 0x0e, "Reserved" },
418 { 0x0f, "Unqualified" },
419 { 0x10, "SCCP failure (ITU only)" },
423 #define RETURN_CAUSE_LENGTH 1
424 static const value_string sccp_return_cause_values [] = {
425 { 0x00, "No translation for an address of such nature" },
426 { 0x01, "No translation for this specific address" },
427 { 0x02, "Subsystem congestion" },
428 { 0x03, "Subsystem failure" },
429 { 0x04, "Unequipped failure" },
430 { 0x05, "MTP failure" },
431 { 0x06, "Network congestion" },
432 { 0x07, "Unqualified" },
433 { 0x08, "Error in message transport" },
434 { 0x09, "Error in local processing" },
435 { 0x0a, "Destination cannot perform reassembly" },
436 { 0x0b, "SCCP failure" },
437 { 0x0c, "Hop counter violation" },
438 { 0x0d, "Segmentation not supported (ITU only)" },
439 { 0x0e, "Segmentation failure (ITU only)" },
440 { 0xf9, "Invalid ISNI routing request (ANSI only)"},
441 { 0xfa, "Unauthorized message (ANSI only)" },
442 { 0xfb, "Message incompatibility (ANSI only)" },
443 { 0xfc, "Cannot perform ISNI constrained routing (ANSI only)" },
444 { 0xfd, "Unable to perform ISNI identification (ANSI only)" },
448 #define RESET_CAUSE_LENGTH 1
449 static const value_string sccp_reset_cause_values [] = {
450 { 0x00, "End user originated" },
451 { 0x01, "SCCP user originated" },
452 { 0x02, "Message out of order - incorrect send sequence number" },
453 { 0x03, "Message out of order - incorrect receive sequence number" },
454 { 0x04, "Remote procedure error - message out of window" },
455 { 0x05, "Remote procedure error - incorrect send sequence number after (re)initialization" },
456 { 0x06, "Remote procedure error - general" },
457 { 0x07, "Remote end user operational" },
458 { 0x08, "Network operational" },
459 { 0x09, "Access operational" },
460 { 0x0a, "Network congestion" },
461 { 0x0b, "Reserved (ITU)/Not obtainable (ANSI)" },
462 { 0x0c, "Unqualified" },
466 #define ERROR_CAUSE_LENGTH 1
467 static const value_string sccp_error_cause_values [] = {
468 { 0x00, "Local Reference Number (LRN) mismatch - unassigned destination LRN" },
469 { 0x01, "Local Reference Number (LRN) mismatch - inconsistent source LRN" },
470 { 0x02, "Point code mismatch" },
471 { 0x03, "Service class mismatch" },
472 { 0x04, "Unqualified" },
476 #define REFUSAL_CAUSE_LENGTH 1
477 static const value_string sccp_refusal_cause_values [] = {
478 { 0x00, "End user originated" },
479 { 0x01, "End user congestion" },
480 { 0x02, "End user failure" },
481 { 0x03, "SCCP user originated" },
482 { 0x04, "Destination address unknown" },
483 { 0x05, "Destination inaccessible" },
484 { 0x06, "Network resource - QOS not available/non-transient" },
485 { 0x07, "Network resource - QOS not available/transient" },
486 { 0x08, "Access failure" },
487 { 0x09, "Access congestion" },
488 { 0x0a, "Subsystem failure" },
489 { 0x0b, "Subsystem congestion" },
490 { 0x0c, "Expiration of connection establishment timer" },
491 { 0x0d, "Incompatible user data" },
492 { 0x0e, "Reserved" },
493 { 0x0f, "Unqualified" },
494 { 0x10, "Hop counter violation" },
495 { 0x11, "SCCP failure (ITU only)" },
496 { 0x12, "No translation for an address of such nature" },
497 { 0x13, "Unequipped user" },
501 #define SEGMENTATION_LENGTH 4
502 #define SEGMENTATION_FIRST_SEGMENT_MASK 0x80
503 #define SEGMENTATION_CLASS_MASK 0x40
504 #define SEGMENTATION_SPARE_MASK 0x30
505 #define SEGMENTATION_REMAINING_MASK 0x0f
506 static const value_string sccp_segmentation_first_segment_values [] = {
507 { 1, "First segment" },
508 { 0, "Not first segment" },
510 static const value_string sccp_segmentation_class_values [] = {
511 { 0, "Class 0 selected" },
512 { 1, "Class 1 selected" },
516 #define HOP_COUNTER_LENGTH 1
518 #define IMPORTANCE_LENGTH 1
519 #define IMPORTANCE_IMPORTANCE_MASK 0x7
522 #define ANSI_ISNI_ROUTING_CONTROL_LENGTH 1
523 #define ANSI_ISNI_MI_MASK 0x01
524 #define ANSI_ISNI_IRI_MASK 0x06
525 #define ANSI_ISNI_RES_MASK 0x08
526 #define ANSI_ISNI_TI_MASK 0x10
527 #define ANSI_ISNI_TI_SHIFT 4
528 #define ANSI_ISNI_COUNTER_MASK 0xe0
530 #define ANSI_ISNI_NETSPEC_MASK 0x03
532 static const value_string sccp_isni_mark_for_id_values [] = {
533 { 0x0, "Do not identify networks" },
534 { 0x1, "Identify networks" },
537 static const value_string sccp_isni_iri_values [] = {
538 { 0x0, "Neither constrained nor suggested ISNI routing" },
539 { 0x1, "Constrained ISNI routing" },
540 { 0x2, "Reserved for suggested ISNI routing" },
544 #define ANSI_ISNI_TYPE_0 0x0
545 #define ANSI_ISNI_TYPE_1 0x1
546 static const value_string sccp_isni_ti_values [] = {
547 { ANSI_ISNI_TYPE_0, "Type zero ISNI parameter format" },
548 { ANSI_ISNI_TYPE_1, "Type one ISNI parameter format" },
552 /* Initialize the protocol and registered fields */
553 static int proto_sccp = -1;
554 static int hf_sccp_message_type = -1;
555 static int hf_sccp_variable_pointer1 = -1;
556 static int hf_sccp_variable_pointer2 = -1;
557 static int hf_sccp_variable_pointer3 = -1;
558 static int hf_sccp_optional_pointer = -1;
559 static int hf_sccp_ssn = -1;
560 static int hf_sccp_gt_digits = -1;
562 /* Called Party address */
563 static int hf_sccp_called_national_indicator = -1;
564 static int hf_sccp_called_routing_indicator = -1;
565 static int hf_sccp_called_itu_global_title_indicator = -1;
566 static int hf_sccp_called_ansi_global_title_indicator = -1;
567 static int hf_sccp_called_itu_ssn_indicator = -1;
568 static int hf_sccp_called_itu_point_code_indicator = -1;
569 static int hf_sccp_called_ansi_ssn_indicator = -1;
570 static int hf_sccp_called_ansi_point_code_indicator = -1;
571 static int hf_sccp_called_ssn = -1;
572 static int hf_sccp_called_pc_member = -1;
573 static int hf_sccp_called_pc_cluster = -1;
574 static int hf_sccp_called_pc_network = -1;
575 static int hf_sccp_called_ansi_pc = -1;
576 static int hf_sccp_called_chinese_pc = -1;
577 static int hf_sccp_called_itu_pc = -1;
578 static int hf_sccp_called_gt_nai = -1;
579 static int hf_sccp_called_gt_oe = -1;
580 static int hf_sccp_called_gt_tt = -1;
581 static int hf_sccp_called_gt_np = -1;
582 static int hf_sccp_called_gt_es = -1;
583 static int hf_sccp_called_gt_digits = -1;
585 /* Calling party address */
586 static int hf_sccp_calling_national_indicator = -1;
587 static int hf_sccp_calling_routing_indicator = -1;
588 static int hf_sccp_calling_itu_global_title_indicator = -1;
589 static int hf_sccp_calling_ansi_global_title_indicator = -1;
590 static int hf_sccp_calling_itu_ssn_indicator = -1;
591 static int hf_sccp_calling_itu_point_code_indicator = -1;
592 static int hf_sccp_calling_ansi_ssn_indicator = -1;
593 static int hf_sccp_calling_ansi_point_code_indicator = -1;
594 static int hf_sccp_calling_ssn = -1;
595 static int hf_sccp_calling_pc_member = -1;
596 static int hf_sccp_calling_pc_cluster = -1;
597 static int hf_sccp_calling_pc_network = -1;
598 static int hf_sccp_calling_ansi_pc = -1;
599 static int hf_sccp_calling_chinese_pc = -1;
600 static int hf_sccp_calling_itu_pc = -1;
601 static int hf_sccp_calling_gt_nai = -1;
602 static int hf_sccp_calling_gt_oe = -1;
603 static int hf_sccp_calling_gt_tt = -1;
604 static int hf_sccp_calling_gt_np = -1;
605 static int hf_sccp_calling_gt_es = -1;
606 static int hf_sccp_calling_gt_digits = -1;
608 /* Other parameter values */
609 static int hf_sccp_dlr = -1;
610 static int hf_sccp_slr = -1;
611 static int hf_sccp_class = -1;
612 static int hf_sccp_handling = -1;
613 static int hf_sccp_more = -1;
614 static int hf_sccp_rsn = -1;
615 static int hf_sccp_sequencing_segmenting_ssn = -1;
616 static int hf_sccp_sequencing_segmenting_rsn = -1;
617 static int hf_sccp_sequencing_segmenting_more = -1;
618 static int hf_sccp_credit = -1;
619 static int hf_sccp_release_cause = -1;
620 static int hf_sccp_return_cause = -1;
621 static int hf_sccp_reset_cause = -1;
622 static int hf_sccp_error_cause = -1;
623 static int hf_sccp_refusal_cause = -1;
624 static int hf_sccp_segmentation_first = -1;
625 static int hf_sccp_segmentation_class = -1;
626 static int hf_sccp_segmentation_remaining = -1;
627 static int hf_sccp_segmentation_slr = -1;
628 static int hf_sccp_hop_counter = -1;
629 static int hf_sccp_importance = -1;
630 static int hf_sccp_ansi_isni_mi = -1;
631 static int hf_sccp_ansi_isni_iri = -1;
632 static int hf_sccp_ansi_isni_ti = -1;
633 static int hf_sccp_ansi_isni_netspec = -1;
634 static int hf_sccp_ansi_isni_counter = -1;
637 /* Initialize the subtree pointers */
638 static gint ett_sccp = -1;
639 static gint ett_sccp_called = -1;
640 static gint ett_sccp_called_ai = -1;
641 static gint ett_sccp_called_pc = -1;
642 static gint ett_sccp_called_gt = -1;
643 static gint ett_sccp_calling = -1;
644 static gint ett_sccp_calling_ai = -1;
645 static gint ett_sccp_calling_pc = -1;
646 static gint ett_sccp_calling_gt = -1;
647 static gint ett_sccp_sequencing_segmenting = -1;
648 static gint ett_sccp_segmentation = -1;
649 static gint ett_sccp_ansi_isni_routing_control = -1;
652 /* Keep track of SSN value of current message so if/when we get to the data
653 * parameter, we can call appropriate sub-dissector. TODO: can this info
654 * be stored elsewhere?
656 static guint8 called_ssn = INVALID_SSN;
657 static guint8 calling_ssn = INVALID_SSN;
659 static dissector_handle_t data_handle;
660 static dissector_table_t sccp_ssn_dissector_table;
663 dissect_sccp_unknown_message(tvbuff_t *message_tvb, proto_tree *sccp_tree)
665 guint32 message_length;
667 message_length = tvb_length(message_tvb);
669 proto_tree_add_text(sccp_tree, message_tvb, 0, message_length,
670 "Unknown message (%u byte%s)",
671 message_length, plurality(message_length, "", "s"));
675 dissect_sccp_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint16 length)
677 proto_tree_add_text(tree, tvb, 0, length, "Unknown parameter 0x%x (%u byte%s)",
678 type, length, plurality(length, "", "s"));
682 dissect_sccp_dlr_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
686 reference = tvb_get_letoh24(tvb, 0);
687 proto_tree_add_uint(tree, hf_sccp_dlr, tvb, 0, length, reference);
691 dissect_sccp_slr_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
695 reference = tvb_get_letoh24(tvb, 0);
696 proto_tree_add_uint(tree, hf_sccp_slr, tvb, 0, length, reference);
700 dissect_sccp_gt_address_information(tvbuff_t *tvb, proto_tree *tree,
701 guint8 length, gboolean even_length,
705 guint8 odd_signal, even_signal = 0x0f;
706 char gt_digits[GT_MAX_SIGNALS] = { 0 };
708 while(offset < length)
710 odd_signal = tvb_get_guint8(tvb, offset) & GT_ODD_SIGNAL_MASK;
711 even_signal = tvb_get_guint8(tvb, offset) & GT_EVEN_SIGNAL_MASK;
712 even_signal >>= GT_EVEN_SIGNAL_SHIFT;
714 strcat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values,
717 /* If the last signal is NOT filler */
718 if (offset != (length - 1) || even_length == TRUE)
719 strcat(gt_digits, val_to_str(even_signal, sccp_address_signal_values,
722 offset += GT_SIGNAL_LENGTH;
725 proto_tree_add_string_format(tree, called ? hf_sccp_called_gt_digits
726 : hf_sccp_calling_gt_digits,
729 "Address information (digits): %s", gt_digits);
730 proto_tree_add_string_hidden(tree, called ? hf_sccp_gt_digits
737 dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint8 length,
738 guint8 gti, gboolean called)
740 proto_item *gt_item = 0;
741 proto_tree *gt_tree = 0;
742 tvbuff_t *signals_tvb;
744 guint8 odd_even, nai, tt, np, es;
745 gboolean even = TRUE;
747 /* Shift GTI to where we can work with it */
750 gt_item = proto_tree_add_text(tree, tvb, offset, length,
751 "Global Title 0x%x (%u byte%s)",
752 gti, length, plurality(length,"", "s"));
753 gt_tree = proto_item_add_subtree(gt_item, called ? ett_sccp_called_gt
754 : ett_sccp_calling_gt);
756 /* Decode Transation Type (if present) */
760 /* Protocol doesn't tell us, so we ASSUME even... */
763 case ITU_AI_GTI_TT_NP_ES:
764 case ITU_AI_GTI_TT_NP_ES_NAI:
765 case ANSI_AI_GTI_TT_NP_ES:
767 tt = tvb_get_guint8(tvb, offset);
768 proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_tt
769 : hf_sccp_calling_gt_tt,
770 tvb, offset, GT_TT_LENGTH, tt);
771 offset += GT_TT_LENGTH;
774 /* Decode Numbering Plan and Encoding Scheme (if present) */
776 case ITU_AI_GTI_TT_NP_ES:
777 case ITU_AI_GTI_TT_NP_ES_NAI:
778 case ANSI_AI_GTI_TT_NP_ES:
780 np = tvb_get_guint8(tvb, offset) & GT_NP_MASK;
781 proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_np
782 : hf_sccp_calling_gt_np,
783 tvb, offset, GT_NP_ES_LENGTH, np);
785 es = tvb_get_guint8(tvb, offset) & GT_ES_MASK;
786 proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_es
787 : hf_sccp_calling_gt_es,
788 tvb, offset, GT_NP_ES_LENGTH, es);
790 even = (es == GT_ES_BCD_EVEN) ? TRUE : FALSE;
792 offset += GT_NP_ES_LENGTH;
795 /* Decode Odd/Even Indicator (if present) */
796 if (gti == ITU_AI_GTI_NAI) {
797 odd_even = tvb_get_guint8(tvb, offset) & GT_OE_MASK;
798 proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_oe
799 : hf_sccp_calling_gt_oe,
800 tvb, offset, GT_NAI_LENGTH, odd_even);
801 even = (odd_even == GT_OE_EVEN) ? TRUE : FALSE;
803 /* offset doesn't change */
806 /* Decode Nature of Address Indicator (if present) */
809 case ITU_AI_GTI_TT_NP_ES_NAI:
810 nai = tvb_get_guint8(tvb, offset) & GT_NAI_MASK;
811 proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_nai
812 : hf_sccp_calling_gt_nai,
813 tvb, offset, GT_NAI_LENGTH, nai);
815 offset += GT_NAI_LENGTH;
818 /* Decode address signal(s) */
819 signals_tvb = tvb_new_subset(tvb, offset, (length - offset),
821 dissect_sccp_gt_address_information(signals_tvb, gt_tree, (length - offset),
827 dissect_sccp_3byte_pc(tvbuff_t *tvb, proto_tree *call_tree, guint8 offset,
831 proto_item *call_pc_item = 0;
832 proto_tree *call_pc_tree = 0;
833 char pc[ANSI_PC_STRING_LENGTH];
836 if (mtp3_standard == ANSI_STANDARD)
839 hf_pc = &hf_sccp_called_ansi_pc;
841 hf_pc = &hf_sccp_calling_ansi_pc;
842 } else /* CHINESE_ITU_STANDARD */ {
844 hf_pc = &hf_sccp_called_chinese_pc;
846 hf_pc = &hf_sccp_calling_chinese_pc;
849 /* create the DPC tree; modified from that in packet-mtp3.c */
850 dpc = tvb_get_ntoh24(tvb, offset);
851 snprintf(pc, sizeof(pc), "%d-%d-%d", (dpc & ANSI_NETWORK_MASK),
852 ((dpc & ANSI_CLUSTER_MASK) >> 8),
853 ((dpc & ANSI_MEMBER_MASK) >> 16));
855 call_pc_item = proto_tree_add_string_format(call_tree, *hf_pc,
856 tvb, offset, ANSI_PC_LENGTH,
859 call_pc_tree = proto_item_add_subtree(call_pc_item,
860 called ? ett_sccp_called_pc
861 : ett_sccp_calling_pc);
863 proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_member
864 : hf_sccp_calling_pc_member,
865 tvb, offset, ANSI_NCM_LENGTH, dpc);
866 offset += ANSI_NCM_LENGTH;
867 proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_cluster
868 : hf_sccp_calling_pc_cluster,
869 tvb, offset, ANSI_NCM_LENGTH, dpc);
870 offset += ANSI_NCM_LENGTH;
871 proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_network
872 : hf_sccp_calling_pc_network,
873 tvb, offset, ANSI_NCM_LENGTH, dpc);
874 offset += ANSI_NCM_LENGTH;
879 /* FUNCTION dissect_sccp_called_calling_param():
880 * Dissect the Calling or Called Party Address parameters.
882 * The boolean 'called' describes whether this function is decoding a
883 * called (TRUE) or calling (FALSE) party address. There is simply too
884 * much code in this function to have 2 copies of it (one for called, one
887 * NOTE: this function is called even when (!tree) so that we can get
888 * the SSN and subsequently call subdissectors (if and when there's a data
889 * parameter). Realistically we should put if (!tree)'s around a lot of the
890 * code, but I think that would make it unreadable--and the expense of not
891 * doing so does not appear to be very high.
894 dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree,
895 guint8 length, gboolean called)
897 proto_item *call_item = 0, *call_ai_item = 0;
898 proto_tree *call_tree = 0, *call_ai_tree = 0;
900 guint8 national = -1, routing_ind, gti, pci, ssni, ssn;
904 call_item = proto_tree_add_text(tree, tvb, 0, length,
905 "%s Party address (%u byte%s)",
906 called ? "Called" : "Calling", length,
907 plurality(length, "", "s"));
908 call_tree = proto_item_add_subtree(call_item, called ? ett_sccp_called
911 call_ai_item = proto_tree_add_text(call_tree, tvb, 0,
912 ADDRESS_INDICATOR_LENGTH,
913 "Address Indicator");
914 call_ai_tree = proto_item_add_subtree(call_ai_item, called ? ett_sccp_called_ai
915 : ett_sccp_calling_ai);
917 if (mtp3_standard == ANSI_STANDARD)
919 national = tvb_get_guint8(tvb, 0) & ANSI_NATIONAL_MASK;
920 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_national_indicator
921 : hf_sccp_calling_national_indicator,
922 tvb, 0, ADDRESS_INDICATOR_LENGTH, national);
925 routing_ind = tvb_get_guint8(tvb, 0) & ROUTING_INDICATOR_MASK;
926 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_routing_indicator
927 : hf_sccp_calling_routing_indicator,
928 tvb, 0, ADDRESS_INDICATOR_LENGTH, routing_ind);
930 gti = tvb_get_guint8(tvb, 0) & GTI_MASK;
932 if (mtp3_standard == ITU_STANDARD ||
933 mtp3_standard == CHINESE_ITU_STANDARD ||
936 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_global_title_indicator
937 : hf_sccp_called_itu_global_title_indicator,
938 tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
940 ssni = tvb_get_guint8(tvb, 0) & ITU_SSN_INDICATOR_MASK;
941 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_ssn_indicator
942 : hf_sccp_calling_itu_ssn_indicator,
943 tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
945 pci = tvb_get_guint8(tvb, 0) & ITU_PC_INDICATOR_MASK;
946 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_point_code_indicator
947 : hf_sccp_calling_itu_point_code_indicator,
948 tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
950 offset = ADDRESS_INDICATOR_LENGTH;
952 /* Dissect PC (if present) */
954 if (mtp3_standard == ITU_STANDARD)
957 dpc = tvb_get_letohs(tvb, offset) & ITU_PC_MASK;
958 proto_tree_add_uint(call_tree, called ? hf_sccp_called_itu_pc
959 : hf_sccp_calling_itu_pc,
960 tvb, offset, ITU_PC_LENGTH, dpc);
961 offset += ITU_PC_LENGTH;
963 } else /* CHINESE_ITU_STANDARD */ {
965 offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
970 /* Dissect SSN (if present) */
972 ssn = tvb_get_guint8(tvb, offset);
980 proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
981 : hf_sccp_calling_ssn,
982 tvb, offset, ADDRESS_SSN_LENGTH, ssn);
983 proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
984 ADDRESS_SSN_LENGTH, ssn);
985 offset += ADDRESS_SSN_LENGTH;
989 return; /* got SSN, that's all we need here... */
991 /* Dissect GT (if present) */
992 if (gti != AI_GTI_NO_GT) {
993 gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
995 dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
999 } else if (mtp3_standard == ANSI_STANDARD) {
1001 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_global_title_indicator
1002 : hf_sccp_calling_ansi_global_title_indicator,
1003 tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
1005 pci = tvb_get_guint8(tvb, 0) & ANSI_PC_INDICATOR_MASK;
1006 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_point_code_indicator
1007 : hf_sccp_calling_ansi_point_code_indicator,
1008 tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
1010 ssni = tvb_get_guint8(tvb, 0) & ANSI_SSN_INDICATOR_MASK;
1011 proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator
1012 : hf_sccp_calling_ansi_ssn_indicator,
1013 tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
1015 offset = ADDRESS_INDICATOR_LENGTH;
1017 /* Dissect SSN (if present) */
1019 ssn = tvb_get_guint8(tvb, offset);
1027 proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
1028 : hf_sccp_calling_ssn,
1029 tvb, offset, ADDRESS_SSN_LENGTH, ssn);
1030 proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
1031 ADDRESS_SSN_LENGTH, ssn);
1032 offset += ADDRESS_SSN_LENGTH;
1036 return; /* got SSN, that's all we need here... */
1038 /* Dissect PC (if present) */
1040 offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
1043 /* Dissect GT (if present) */
1044 if (gti != AI_GTI_NO_GT) {
1045 gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
1047 dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
1056 dissect_sccp_called_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1058 dissect_sccp_called_calling_param(tvb, tree, length, TRUE);
1062 dissect_sccp_calling_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1064 dissect_sccp_called_calling_param(tvb, tree, length, FALSE);
1068 dissect_sccp_class_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1070 guint8 class, handling;
1072 class = tvb_get_guint8(tvb, 0) & CLASS_CLASS_MASK;
1073 handling = tvb_get_guint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK;
1075 proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, class);
1077 if (class == 0 || class == 1)
1078 proto_tree_add_uint(tree, hf_sccp_handling, tvb, 0, length, handling);
1082 dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1086 more = tvb_get_guint8(tvb, 0) & SEGMENTING_REASSEMBLING_MASK;
1087 proto_tree_add_uint(tree, hf_sccp_more, tvb, 0, length, more);
1091 dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1095 rsn = tvb_get_guint8(tvb, 0) >> 1;
1096 proto_tree_add_uint(tree, hf_sccp_rsn, tvb, 0, length, rsn);
1100 dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1102 guint8 rsn, ssn, more;
1103 proto_item *param_item;
1104 proto_tree *param_tree;
1106 ssn = tvb_get_guint8(tvb, 0) >> 1;
1107 rsn = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) >> 1;
1108 more = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) & SEQUENCING_SEGMENTING_MORE_MASK;
1110 param_item = proto_tree_add_text(tree, tvb, 0, length,
1111 val_to_str(PARAMETER_SEQUENCING_SEGMENTING,
1112 sccp_parameter_values, "Unknown"));
1113 param_tree = proto_item_add_subtree(param_item,
1114 ett_sccp_sequencing_segmenting);
1116 proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_ssn, tvb, 0,
1117 SEQUENCING_SEGMENTING_SSN_LENGTH, ssn);
1118 proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_rsn, tvb,
1119 SEQUENCING_SEGMENTING_SSN_LENGTH,
1120 SEQUENCING_SEGMENTING_RSN_LENGTH, rsn);
1121 proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_more, tvb,
1122 SEQUENCING_SEGMENTING_SSN_LENGTH,
1123 SEQUENCING_SEGMENTING_RSN_LENGTH, more);
1127 dissect_sccp_credit_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1131 credit = tvb_get_guint8(tvb, 0);
1132 proto_tree_add_uint(tree, hf_sccp_credit, tvb, 0, length, credit);
1136 dissect_sccp_release_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1140 cause = tvb_get_guint8(tvb, 0);
1141 proto_tree_add_uint(tree, hf_sccp_release_cause, tvb, 0, length, cause);
1145 dissect_sccp_return_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1149 cause = tvb_get_guint8(tvb, 0);
1150 proto_tree_add_uint(tree, hf_sccp_return_cause, tvb, 0, length, cause);
1154 dissect_sccp_reset_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1158 cause = tvb_get_guint8(tvb, 0);
1159 proto_tree_add_uint(tree, hf_sccp_reset_cause, tvb, 0, length, cause);
1163 dissect_sccp_error_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1167 cause = tvb_get_guint8(tvb, 0);
1168 proto_tree_add_uint(tree, hf_sccp_error_cause, tvb, 0, length, cause);
1172 dissect_sccp_refusal_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1176 cause = tvb_get_guint8(tvb, 0);
1177 proto_tree_add_uint(tree, hf_sccp_refusal_cause, tvb, 0, length, cause);
1180 /* This function is used for both data and long data (ITU only) parameters */
1182 dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1185 /* Try subdissectors (if we found a valid SSN on the current message) */
1186 if ((called_ssn != INVALID_SSN &&
1187 dissector_try_port(sccp_ssn_dissector_table, called_ssn, tvb, pinfo,
1189 (calling_ssn != INVALID_SSN &&
1190 dissector_try_port(sccp_ssn_dissector_table, calling_ssn, tvb, pinfo,
1194 /* No sub-dissection occured, treat it as raw data */
1195 call_dissector(data_handle, tvb, pinfo, tree);
1199 dissect_sccp_segmentation_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1201 guint8 first, class, remaining;
1203 proto_item *param_item;
1204 proto_tree *param_tree;
1206 first = tvb_get_guint8(tvb, 0) & SEGMENTATION_FIRST_SEGMENT_MASK;
1207 class = tvb_get_guint8(tvb, 0) & SEGMENTATION_CLASS_MASK;
1208 remaining = tvb_get_guint8(tvb, 0) & SEGMENTATION_REMAINING_MASK;
1210 slr = tvb_get_letoh24(tvb, 1);
1212 param_item = proto_tree_add_text(tree, tvb, 0, length,
1213 val_to_str(PARAMETER_SEGMENTATION,
1214 sccp_parameter_values, "Unknown"));
1215 param_tree = proto_item_add_subtree(param_item, ett_sccp_segmentation);
1217 proto_tree_add_uint(param_tree, hf_sccp_segmentation_first, tvb, 0, length,
1219 proto_tree_add_uint(param_tree, hf_sccp_segmentation_class, tvb, 0, length,
1221 proto_tree_add_uint(param_tree, hf_sccp_segmentation_remaining, tvb, 0,
1223 proto_tree_add_uint(param_tree, hf_sccp_segmentation_slr, tvb, 1, length,
1228 dissect_sccp_hop_counter_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1232 hops = tvb_get_guint8(tvb, 0);
1233 proto_tree_add_uint(tree, hf_sccp_hop_counter, tvb, 0, length, hops);
1237 dissect_sccp_importance_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1241 importance = tvb_get_guint8(tvb, 0) & IMPORTANCE_IMPORTANCE_MASK;
1242 proto_tree_add_uint(tree, hf_sccp_importance, tvb, 0, length, importance);
1246 dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
1248 guint8 mi, iri, ti, network, netspec;
1250 proto_item *param_item;
1251 proto_tree *param_tree;
1253 /* Create a subtree for ISNI Routing Control */
1254 param_item = proto_tree_add_text(tree, tvb, offset, ANSI_ISNI_ROUTING_CONTROL_LENGTH,
1255 "ISNI Routing Control");
1256 param_tree = proto_item_add_subtree(param_item,
1257 ett_sccp_ansi_isni_routing_control);
1259 mi = tvb_get_guint8(tvb, offset) & ANSI_ISNI_MI_MASK;
1260 proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_mi, tvb, offset,
1261 ANSI_ISNI_ROUTING_CONTROL_LENGTH, mi);
1263 iri = tvb_get_guint8(tvb, offset) & ANSI_ISNI_IRI_MASK;
1264 proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_iri, tvb, offset,
1265 ANSI_ISNI_ROUTING_CONTROL_LENGTH, iri);
1267 ti = tvb_get_guint8(tvb, offset) & ANSI_ISNI_TI_MASK;
1268 proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_ti, tvb, offset,
1269 ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
1271 offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
1273 if ((ti >> ANSI_ISNI_TI_SHIFT) == ANSI_ISNI_TYPE_1) {
1274 netspec = tvb_get_guint8(tvb, offset) & ANSI_ISNI_NETSPEC_MASK;
1275 proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_netspec, tvb, offset,
1276 ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
1277 offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
1280 while (offset < length) {
1282 network = tvb_get_guint8(tvb, offset);
1283 proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
1284 "Network ID network: %d", network);
1287 network = tvb_get_guint8(tvb, offset);
1288 proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
1289 "Network ID cluster: %d", network);
1295 /* FUNCTION dissect_sccp_parameter():
1296 * Dissect a parameter given its type, offset into tvb, and length.
1299 dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
1300 proto_tree *tree, guint8 parameter_type, guint16 offset,
1301 guint16 parameter_length)
1303 tvbuff_t *parameter_tvb;
1305 switch (parameter_type) {
1306 case PARAMETER_CALLED_PARTY_ADDRESS:
1307 case PARAMETER_CALLING_PARTY_ADDRESS:
1308 case PARAMETER_DATA:
1309 case PARAMETER_LONG_DATA:
1310 /* These parameters must be dissected even if !sccp_tree (so that
1311 * subdissectors can be called).
1317 return(parameter_length);
1321 parameter_tvb = tvb_new_subset(tvb, offset, parameter_length, parameter_length);
1323 switch (parameter_type) {
1325 case PARAMETER_END_OF_OPTIONAL_PARAMETERS:
1326 proto_tree_add_text(sccp_tree, tvb, offset, parameter_length,
1330 case PARAMETER_DESTINATION_LOCAL_REFERENCE:
1331 dissect_sccp_dlr_param(parameter_tvb, sccp_tree, parameter_length);
1334 case PARAMETER_SOURCE_LOCAL_REFERENCE:
1335 dissect_sccp_slr_param(parameter_tvb, sccp_tree, parameter_length);
1338 case PARAMETER_CALLED_PARTY_ADDRESS:
1339 dissect_sccp_called_param(parameter_tvb, sccp_tree, parameter_length);
1342 case PARAMETER_CALLING_PARTY_ADDRESS:
1343 dissect_sccp_calling_param(parameter_tvb, sccp_tree, parameter_length);
1346 case PARAMETER_CLASS:
1347 dissect_sccp_class_param(parameter_tvb, sccp_tree, parameter_length);
1350 case PARAMETER_SEGMENTING_REASSEMBLING:
1351 dissect_sccp_segmenting_reassembling_param(parameter_tvb, sccp_tree,
1355 case PARAMETER_RECEIVE_SEQUENCE_NUMBER:
1356 dissect_sccp_receive_sequence_number_param(parameter_tvb, sccp_tree,
1360 case PARAMETER_SEQUENCING_SEGMENTING:
1361 dissect_sccp_sequencing_segmenting_param(parameter_tvb, sccp_tree,
1365 case PARAMETER_CREDIT:
1366 dissect_sccp_credit_param(parameter_tvb, sccp_tree, parameter_length);
1369 case PARAMETER_RELEASE_CAUSE:
1370 dissect_sccp_release_cause_param(parameter_tvb, sccp_tree, parameter_length);
1373 case PARAMETER_RETURN_CAUSE:
1374 dissect_sccp_return_cause_param(parameter_tvb, sccp_tree, parameter_length);
1377 case PARAMETER_RESET_CAUSE:
1378 dissect_sccp_reset_cause_param(parameter_tvb, sccp_tree, parameter_length);
1381 case PARAMETER_ERROR_CAUSE:
1382 dissect_sccp_error_cause_param(parameter_tvb, sccp_tree, parameter_length);
1385 case PARAMETER_REFUSAL_CAUSE:
1386 dissect_sccp_refusal_cause_param(parameter_tvb, sccp_tree, parameter_length);
1389 case PARAMETER_DATA:
1390 dissect_sccp_data_param(parameter_tvb, pinfo, tree);
1392 /* TODO? Re-adjust length of SCCP item since it may be sub-dissected */
1393 /* sccp_length = proto_item_get_len(sccp_item);
1394 * sccp_length -= parameter_length;
1395 * proto_item_set_len(sccp_item, sccp_length);
1399 case PARAMETER_SEGMENTATION:
1400 dissect_sccp_segmentation_param(parameter_tvb, sccp_tree, parameter_length);
1403 case PARAMETER_HOP_COUNTER:
1404 dissect_sccp_hop_counter_param(parameter_tvb, sccp_tree, parameter_length);
1407 case PARAMETER_IMPORTANCE:
1408 if (mtp3_standard != ANSI_STANDARD)
1409 dissect_sccp_importance_param(parameter_tvb, sccp_tree, parameter_length);
1411 dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1415 case PARAMETER_LONG_DATA:
1416 if (mtp3_standard != ANSI_STANDARD)
1417 dissect_sccp_data_param(parameter_tvb, pinfo, tree);
1419 dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1423 case PARAMETER_ISNI:
1424 if (mtp3_standard != ANSI_STANDARD)
1425 dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1428 dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
1432 dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
1437 return(parameter_length);
1440 /* FUNCTION dissect_sccp_variable_parameter():
1441 * Dissect a variable parameter given its type and offset into tvb. Length
1442 * of the parameter is gotten from tvb[0].
1443 * Length returned is sum of (length + parameter).
1446 dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo,
1447 proto_tree *sccp_tree, proto_tree *tree,
1448 guint8 parameter_type, guint16 offset)
1450 guint16 parameter_length;
1451 guint8 length_length;
1453 if (parameter_type != PARAMETER_LONG_DATA)
1455 parameter_length = tvb_get_guint8(tvb, offset);
1456 length_length = PARAMETER_LENGTH_LENGTH;
1460 /* Long data parameter has 16 bit length */
1461 parameter_length = tvb_get_letohs(tvb, offset);
1462 length_length = PARAMETER_LONG_DATA_LENGTH_LENGTH;
1465 /* TODO? I find this annoying, but it could possibly useful for debugging.
1466 * Make it a preference?
1468 * proto_tree_add_text(sccp_tree, tvb, offset, length_length,
1470 * val_to_str(parameter_type, sccp_parameter_values,
1472 * parameter_length);
1475 offset += length_length;
1477 dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
1480 return(parameter_length + length_length);
1483 /* FUNCTION dissect_sccp_optional_parameters():
1484 * Dissect all the optional parameters given the start of the optional
1485 * parameters into tvb. Parameter types and lengths are read from tvb.
1488 dissect_sccp_optional_parameters(tvbuff_t *tvb, packet_info *pinfo,
1489 proto_tree *sccp_tree, proto_tree *tree,
1492 guint8 parameter_type;
1494 while ((parameter_type = tvb_get_guint8(tvb, offset)) !=
1495 PARAMETER_END_OF_OPTIONAL_PARAMETERS) {
1497 offset += PARAMETER_TYPE_LENGTH;
1498 offset += dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1499 parameter_type, offset);
1502 /* Process end of optional parameters */
1503 dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
1504 END_OF_OPTIONAL_PARAMETERS_LENGTH);
1510 dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
1513 guint8 message_type;
1514 guint16 variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
1515 guint16 optional_pointer = 0;
1518 /* Macro for getting pointer to mandatory variable parameters */
1519 #define VARIABLE_POINTER(var, hf_var, ptr_size) \
1520 if (ptr_size == POINTER_LENGTH) \
1521 var = tvb_get_guint8(tvb, offset); \
1523 var = tvb_get_letohs(tvb, offset); \
1524 proto_tree_add_uint(sccp_tree, hf_var, tvb, \
1525 offset, ptr_size, var); \
1529 /* Macro for getting pointer to optional parameters */
1530 #define OPTIONAL_POINTER(ptr_size) \
1531 if (ptr_size == POINTER_LENGTH) \
1532 optional_pointer = tvb_get_guint8(tvb, offset); \
1534 optional_pointer = tvb_get_letohs(tvb, offset); \
1535 proto_tree_add_uint(sccp_tree, hf_sccp_optional_pointer, tvb, \
1536 offset, ptr_size, optional_pointer); \
1537 optional_pointer += offset; \
1541 /* Extract the message type; all other processing is based on this */
1542 message_type = tvb_get_guint8(tvb, MESSAGE_TYPE_OFFSET);
1543 offset = MESSAGE_TYPE_LENGTH;
1545 if (check_col(pinfo->cinfo, COL_INFO))
1546 col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
1547 val_to_str(message_type, sccp_message_type_acro_values, "Unknown"));
1550 /* add the message type to the protocol tree */
1551 proto_tree_add_uint(sccp_tree, hf_sccp_message_type, tvb,
1552 MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, message_type);
1556 /* Starting a new message dissection; clear the global SSN values */
1557 called_ssn = INVALID_SSN;
1558 calling_ssn = INVALID_SSN;
1560 switch(message_type) {
1561 case MESSAGE_TYPE_CR:
1562 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1563 PARAMETER_SOURCE_LOCAL_REFERENCE,
1564 offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1565 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1566 PARAMETER_CLASS, offset,
1567 PROTOCOL_CLASS_LENGTH);
1569 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1570 OPTIONAL_POINTER(POINTER_LENGTH)
1572 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1573 PARAMETER_CALLED_PARTY_ADDRESS,
1577 case MESSAGE_TYPE_CC:
1578 /* TODO: connection has been established; theoretically we could keep
1579 * keep track of the SLR/DLR with the called/calling from the CR and
1580 * track the connection (e.g., on subsequent messages regarding this
1581 * SLR we could set the global vars "call*_ssn" so data could get
1584 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1585 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1587 DESTINATION_LOCAL_REFERENCE_LENGTH);
1588 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1589 PARAMETER_SOURCE_LOCAL_REFERENCE,
1590 offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1591 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1592 PARAMETER_CLASS, offset,
1593 PROTOCOL_CLASS_LENGTH);
1594 OPTIONAL_POINTER(POINTER_LENGTH)
1597 case MESSAGE_TYPE_CREF:
1598 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1599 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1601 DESTINATION_LOCAL_REFERENCE_LENGTH);
1602 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1603 PARAMETER_REFUSAL_CAUSE, offset,
1604 REFUSAL_CAUSE_LENGTH);
1605 OPTIONAL_POINTER(POINTER_LENGTH)
1608 case MESSAGE_TYPE_RLSD:
1609 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1610 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1612 DESTINATION_LOCAL_REFERENCE_LENGTH);
1613 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1614 PARAMETER_SOURCE_LOCAL_REFERENCE,
1615 offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1616 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1617 PARAMETER_RELEASE_CAUSE, offset,
1618 RELEASE_CAUSE_LENGTH);
1620 OPTIONAL_POINTER(POINTER_LENGTH)
1623 case MESSAGE_TYPE_RLC:
1624 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1625 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1627 DESTINATION_LOCAL_REFERENCE_LENGTH);
1628 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1629 PARAMETER_SOURCE_LOCAL_REFERENCE,
1630 offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1633 case MESSAGE_TYPE_DT1:
1634 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1635 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1637 DESTINATION_LOCAL_REFERENCE_LENGTH);
1638 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1639 PARAMETER_SEGMENTING_REASSEMBLING,
1640 offset, SEGMENTING_REASSEMBLING_LENGTH);
1642 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1643 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1647 case MESSAGE_TYPE_DT2:
1648 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1649 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1651 DESTINATION_LOCAL_REFERENCE_LENGTH);
1652 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1653 PARAMETER_SEQUENCING_SEGMENTING, offset,
1654 SEQUENCING_SEGMENTING_LENGTH);
1657 case MESSAGE_TYPE_AK:
1658 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1659 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1661 DESTINATION_LOCAL_REFERENCE_LENGTH);
1662 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1663 PARAMETER_RECEIVE_SEQUENCE_NUMBER,
1664 offset, RECEIVE_SEQUENCE_NUMBER_LENGTH);
1665 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1666 PARAMETER_CREDIT, offset, CREDIT_LENGTH);
1669 case MESSAGE_TYPE_UDT:
1670 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1671 PARAMETER_CLASS, offset,
1672 PROTOCOL_CLASS_LENGTH);
1673 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1674 VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
1675 VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
1677 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1678 PARAMETER_CALLED_PARTY_ADDRESS,
1680 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1681 PARAMETER_CALLING_PARTY_ADDRESS,
1683 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1687 case MESSAGE_TYPE_UDTS:
1688 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1689 PARAMETER_RETURN_CAUSE, offset,
1690 RETURN_CAUSE_LENGTH);
1692 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1693 VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
1694 VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
1696 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1697 PARAMETER_CALLED_PARTY_ADDRESS,
1700 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1701 PARAMETER_CALLING_PARTY_ADDRESS,
1704 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1708 case MESSAGE_TYPE_ED:
1709 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1710 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1712 DESTINATION_LOCAL_REFERENCE_LENGTH);
1714 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1715 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1719 case MESSAGE_TYPE_EA:
1720 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1721 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1723 DESTINATION_LOCAL_REFERENCE_LENGTH);
1726 case MESSAGE_TYPE_RSR:
1727 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1728 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1730 DESTINATION_LOCAL_REFERENCE_LENGTH);
1731 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1732 PARAMETER_SOURCE_LOCAL_REFERENCE,
1733 offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1734 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1735 PARAMETER_RESET_CAUSE, offset,
1736 RESET_CAUSE_LENGTH);
1739 case MESSAGE_TYPE_RSC:
1740 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1741 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1743 DESTINATION_LOCAL_REFERENCE_LENGTH);
1744 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1745 PARAMETER_SOURCE_LOCAL_REFERENCE,
1746 offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1749 case MESSAGE_TYPE_ERR:
1750 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1751 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1753 DESTINATION_LOCAL_REFERENCE_LENGTH);
1754 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1755 PARAMETER_ERROR_CAUSE, offset,
1756 ERROR_CAUSE_LENGTH);
1759 case MESSAGE_TYPE_IT:
1760 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1761 PARAMETER_DESTINATION_LOCAL_REFERENCE,
1763 DESTINATION_LOCAL_REFERENCE_LENGTH);
1764 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1765 PARAMETER_SOURCE_LOCAL_REFERENCE,
1766 offset, SOURCE_LOCAL_REFERENCE_LENGTH);
1767 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1768 PARAMETER_CLASS, offset,
1769 PROTOCOL_CLASS_LENGTH);
1770 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1771 PARAMETER_SEQUENCING_SEGMENTING,
1772 offset, SEQUENCING_SEGMENTING_LENGTH);
1773 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1774 PARAMETER_CREDIT, offset, CREDIT_LENGTH);
1777 case MESSAGE_TYPE_XUDT:
1778 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1779 PARAMETER_CLASS, offset,
1780 PROTOCOL_CLASS_LENGTH);
1781 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1782 PARAMETER_HOP_COUNTER, offset,
1783 HOP_COUNTER_LENGTH);
1785 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1786 VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
1787 VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
1788 OPTIONAL_POINTER(POINTER_LENGTH)
1790 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1791 PARAMETER_CALLED_PARTY_ADDRESS,
1793 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1794 PARAMETER_CALLING_PARTY_ADDRESS,
1796 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1800 case MESSAGE_TYPE_XUDTS:
1801 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1802 PARAMETER_RETURN_CAUSE, offset,
1803 RETURN_CAUSE_LENGTH);
1804 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1805 PARAMETER_HOP_COUNTER, offset,
1806 HOP_COUNTER_LENGTH);
1808 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
1809 VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
1810 VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
1811 OPTIONAL_POINTER(POINTER_LENGTH)
1813 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1814 PARAMETER_CALLED_PARTY_ADDRESS,
1816 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1817 PARAMETER_CALLING_PARTY_ADDRESS,
1819 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
1823 case MESSAGE_TYPE_LUDT:
1824 if (mtp3_standard != ANSI_STANDARD)
1826 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1827 PARAMETER_CLASS, offset,
1828 PROTOCOL_CLASS_LENGTH);
1829 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1830 PARAMETER_HOP_COUNTER, offset,
1831 HOP_COUNTER_LENGTH);
1833 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
1834 VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
1835 VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
1836 OPTIONAL_POINTER(POINTER_LENGTH_LONG)
1838 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1839 PARAMETER_CALLED_PARTY_ADDRESS,
1841 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1842 PARAMETER_CALLING_PARTY_ADDRESS,
1844 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1845 PARAMETER_LONG_DATA, variable_pointer3);
1847 dissect_sccp_unknown_message(tvb, sccp_tree);
1850 case MESSAGE_TYPE_LUDTS:
1851 if (mtp3_standard != ANSI_STANDARD)
1853 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1854 PARAMETER_RETURN_CAUSE, offset,
1855 RETURN_CAUSE_LENGTH);
1856 offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
1857 PARAMETER_HOP_COUNTER, offset,
1858 HOP_COUNTER_LENGTH);
1860 VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
1861 VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
1862 VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
1863 OPTIONAL_POINTER(POINTER_LENGTH_LONG)
1865 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1866 PARAMETER_CALLED_PARTY_ADDRESS,
1868 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1869 PARAMETER_CALLING_PARTY_ADDRESS,
1871 dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
1872 PARAMETER_LONG_DATA, variable_pointer3);
1874 dissect_sccp_unknown_message(tvb, sccp_tree);
1878 dissect_sccp_unknown_message(tvb, sccp_tree);
1881 if (optional_pointer)
1882 dissect_sccp_optional_parameters(tvb, pinfo, sccp_tree, tree,
1888 dissect_sccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1890 proto_item *sccp_item;
1891 proto_tree *sccp_tree = NULL;
1893 /* Make entry in the Protocol column on summary display */
1894 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1895 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP");
1897 /* In the interest of speed, if "tree" is NULL, don't do any work not
1898 necessary to generate protocol tree items. */
1900 /* create the sccp protocol tree */
1901 sccp_item = proto_tree_add_item(tree, proto_sccp, tvb, 0, -1, FALSE);
1902 sccp_tree = proto_item_add_subtree(sccp_item, ett_sccp);
1905 /* dissect the message */
1906 dissect_sccp_message(tvb, pinfo, sccp_tree, tree);
1909 /* Register the protocol with Ethereal */
1911 proto_register_sccp(void)
1913 /* Setup list of header fields */
1914 static hf_register_info hf[] = {
1915 { &hf_sccp_message_type,
1916 { "Message Type", "sccp.message_type",
1917 FT_UINT8, BASE_HEX, VALS(sccp_message_type_values), 0x0,
1919 { &hf_sccp_variable_pointer1,
1920 { "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1",
1921 FT_UINT16, BASE_DEC, NULL, 0x0,
1923 { &hf_sccp_variable_pointer2,
1924 { "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2",
1925 FT_UINT16, BASE_DEC, NULL, 0x0,
1927 { &hf_sccp_variable_pointer3,
1928 { "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3",
1929 FT_UINT16, BASE_DEC, NULL, 0x0,
1931 { &hf_sccp_optional_pointer,
1932 { "Pointer to Optional parameter", "sccp.optional_pointer",
1933 FT_UINT16, BASE_DEC, NULL, 0x0,
1936 { "Called or Calling SubSystem Number", "sccp.ssn",
1937 FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
1939 { &hf_sccp_gt_digits,
1940 { "Called or Calling GT Digits",
1942 FT_STRING, BASE_NONE, NULL, 0x0,
1945 { &hf_sccp_called_national_indicator,
1946 { "National Indicator", "sccp.called.ni",
1947 FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
1949 { &hf_sccp_called_routing_indicator,
1950 { "Routing Indicator", "sccp.called.ri",
1951 FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
1953 { &hf_sccp_called_itu_global_title_indicator,
1954 { "Global Title Indicator", "sccp.called.gti",
1955 FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
1957 { &hf_sccp_called_ansi_global_title_indicator,
1958 { "Global Title Indicator", "sccp.called.gti",
1959 FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
1961 { &hf_sccp_called_itu_ssn_indicator,
1962 { "SubSystem Number Indicator", "sccp.called.ssni",
1963 FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
1965 { &hf_sccp_called_itu_point_code_indicator,
1966 { "Point Code Indicator", "sccp.called.pci",
1967 FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
1969 { &hf_sccp_called_ansi_ssn_indicator,
1970 { "SubSystem Number Indicator", "sccp.called.ssni",
1971 FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
1973 { &hf_sccp_called_ansi_point_code_indicator,
1974 { "Point Code Indicator", "sccp.called.pci",
1975 FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
1977 { &hf_sccp_called_ssn,
1978 { "SubSystem Number", "sccp.called.ssn",
1979 FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
1981 { &hf_sccp_called_itu_pc,
1982 { "PC", "sccp.called.pc",
1983 FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
1985 { &hf_sccp_called_ansi_pc,
1986 { "PC", "sccp.called.ansi_pc",
1987 FT_STRING, BASE_NONE, NULL, 0x0,
1989 { &hf_sccp_called_chinese_pc,
1990 { "PC", "sccp.called.chinese_pc",
1991 FT_STRING, BASE_NONE, NULL, 0x0,
1993 { &hf_sccp_called_pc_network,
1995 "sccp.called.network",
1996 FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
1998 { &hf_sccp_called_pc_cluster,
2000 "sccp.called.cluster",
2001 FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
2003 { &hf_sccp_called_pc_member,
2005 "sccp.called.member",
2006 FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
2008 { &hf_sccp_called_gt_nai,
2009 { "Nature of Address Indicator",
2011 FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
2013 { &hf_sccp_called_gt_oe,
2014 { "Odd/Even Indicator",
2016 FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
2018 { &hf_sccp_called_gt_tt,
2019 { "Translation Type",
2021 FT_UINT8, BASE_HEX, NULL, 0x0,
2023 { &hf_sccp_called_gt_np,
2026 FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
2028 { &hf_sccp_called_gt_es,
2029 { "Encoding Scheme",
2031 FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
2033 { &hf_sccp_called_gt_digits,
2035 "sccp.called.digits",
2036 FT_STRING, BASE_NONE, NULL, 0x0,
2039 { &hf_sccp_calling_national_indicator,
2040 { "National Indicator", "sccp.calling.ni",
2041 FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
2043 { &hf_sccp_calling_routing_indicator,
2044 { "Routing Indicator", "sccp.calling.ri",
2045 FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
2047 { &hf_sccp_calling_itu_global_title_indicator,
2048 { "Global Title Indicator", "sccp.calling.gti",
2049 FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
2051 { &hf_sccp_calling_ansi_global_title_indicator,
2052 { "Global Title Indicator", "sccp.calling.gti",
2053 FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
2055 { &hf_sccp_calling_itu_ssn_indicator,
2056 { "SubSystem Number Indicator", "sccp.calling.ssni",
2057 FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
2059 { &hf_sccp_calling_itu_point_code_indicator,
2060 { "Point Code Indicator", "sccp.calling.pci",
2061 FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
2063 { &hf_sccp_calling_ansi_ssn_indicator,
2064 { "SubSystem Number Indicator", "sccp.calling.ssni",
2065 FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
2067 { &hf_sccp_calling_ansi_point_code_indicator,
2068 { "Point Code Indicator", "sccp.calling.pci",
2069 FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
2071 { &hf_sccp_calling_ssn,
2072 { "SubSystem Number", "sccp.calling.ssn",
2073 FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
2075 { &hf_sccp_calling_itu_pc,
2076 { "PC", "sccp.calling.pc",
2077 FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
2079 { &hf_sccp_calling_ansi_pc,
2080 { "PC", "sccp.calling.ansi_pc",
2081 FT_STRING, BASE_NONE, NULL, 0x0,
2083 { &hf_sccp_calling_chinese_pc,
2084 { "PC", "sccp.calling.chinese_pc",
2085 FT_STRING, BASE_NONE, NULL, 0x0,
2087 { &hf_sccp_calling_pc_network,
2089 "sccp.calling.network",
2090 FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
2092 { &hf_sccp_calling_pc_cluster,
2094 "sccp.calling.cluster",
2095 FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
2097 { &hf_sccp_calling_pc_member,
2099 "sccp.calling.member",
2100 FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
2102 { &hf_sccp_calling_gt_nai,
2103 { "Nature of Address Indicator",
2105 FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
2107 { &hf_sccp_calling_gt_oe,
2108 { "Odd/Even Indicator",
2110 FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
2112 { &hf_sccp_calling_gt_tt,
2113 { "Translation Type",
2115 FT_UINT8, BASE_HEX, NULL, 0x0,
2117 { &hf_sccp_calling_gt_np,
2120 FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
2122 { &hf_sccp_calling_gt_es,
2123 { "Encoding Scheme",
2125 FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
2127 { &hf_sccp_calling_gt_digits,
2129 "sccp.calling.digits",
2130 FT_STRING, BASE_NONE, NULL, 0x0,
2134 { "Destination Local Reference", "sccp.dlr",
2135 FT_UINT24, BASE_HEX, NULL, 0x0,
2138 { "Source Local Reference", "sccp.slr",
2139 FT_UINT24, BASE_HEX, NULL, 0x0,
2142 { "Class", "sccp.class",
2143 FT_UINT8, BASE_HEX, NULL, CLASS_CLASS_MASK,
2145 { &hf_sccp_handling,
2146 { "Message handling", "sccp.handling",
2147 FT_UINT8, BASE_HEX, VALS(sccp_class_handling_values), CLASS_SPARE_HANDLING_MASK,
2150 { "More data", "sccp.more",
2151 FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEGMENTING_REASSEMBLING_MASK,
2154 { "Receive Sequence Number", "sccp.rsn",
2155 FT_UINT8, BASE_HEX, NULL, RSN_MASK,
2157 { &hf_sccp_sequencing_segmenting_ssn,
2158 { "Sequencing Segmenting: Send Sequence Number", "sccp.sequencing_segmenting.ssn",
2159 FT_UINT8, BASE_HEX, NULL, SEND_SEQUENCE_NUMBER_MASK,
2161 { &hf_sccp_sequencing_segmenting_rsn,
2162 { "Sequencing Segmenting: Receive Sequence Number", "sccp.sequencing_segmenting.rsn",
2163 FT_UINT8, BASE_HEX, NULL, RECEIVE_SEQUENCE_NUMBER_MASK,
2165 { &hf_sccp_sequencing_segmenting_more,
2166 { "Sequencing Segmenting: More", "sccp.sequencing_segmenting.more",
2167 FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEQUENCING_SEGMENTING_MORE_MASK,
2170 { "Credit", "sccp.credit",
2171 FT_UINT8, BASE_HEX, NULL, 0x0,
2173 { &hf_sccp_release_cause,
2174 { "Release Cause", "sccp.release_cause",
2175 FT_UINT8, BASE_HEX, VALS(sccp_release_cause_values), 0x0,
2177 { &hf_sccp_return_cause,
2178 { "Return Cause", "sccp.return_cause",
2179 FT_UINT8, BASE_HEX, VALS(sccp_return_cause_values), 0x0,
2181 { &hf_sccp_reset_cause,
2182 { "Reset Cause", "sccp.reset_cause",
2183 FT_UINT8, BASE_HEX, VALS(sccp_reset_cause_values), 0x0,
2185 { &hf_sccp_error_cause,
2186 { "Error Cause", "sccp.error_cause",
2187 FT_UINT8, BASE_HEX, VALS(sccp_error_cause_values), 0x0,
2189 { &hf_sccp_refusal_cause,
2190 { "Refusal Cause", "sccp.refusal_cause",
2191 FT_UINT8, BASE_HEX, VALS(sccp_refusal_cause_values), 0x0,
2193 { &hf_sccp_segmentation_first,
2194 { "Segmentation: First", "sccp.segmentation.first",
2195 FT_UINT8, BASE_HEX, VALS(sccp_segmentation_first_segment_values), SEGMENTATION_FIRST_SEGMENT_MASK,
2197 { &hf_sccp_segmentation_class,
2198 { "Segmentation: Class", "sccp.segmentation.class",
2199 FT_UINT8, BASE_HEX, VALS(sccp_segmentation_class_values), SEGMENTATION_CLASS_MASK,
2201 { &hf_sccp_segmentation_remaining,
2202 { "Segmentation: Remaining", "sccp.segmentation.remaining",
2203 FT_UINT8, BASE_HEX, NULL, SEGMENTATION_REMAINING_MASK,
2205 { &hf_sccp_segmentation_slr,
2206 { "Segmentation: Source Local Reference", "sccp.segmentation.slr",
2207 FT_UINT24, BASE_HEX, NULL, 0x0,
2209 { &hf_sccp_hop_counter,
2210 { "Hop Counter", "sccp.hops",
2211 FT_UINT8, BASE_HEX, NULL, 0x0,
2213 { &hf_sccp_importance,
2214 { "Importance", "sccp.importance",
2215 FT_UINT8, BASE_HEX, NULL, IMPORTANCE_IMPORTANCE_MASK,
2218 /* ISNI is ANSI only */
2219 { &hf_sccp_ansi_isni_mi,
2220 { "ISNI Mark for Identification Indicator", "sccp.isni.mi",
2221 FT_UINT8, BASE_HEX, VALS(sccp_isni_mark_for_id_values), ANSI_ISNI_MI_MASK,
2223 { &hf_sccp_ansi_isni_iri,
2224 { "ISNI Routing Indicator", "sccp.isni.iri",
2225 FT_UINT8, BASE_HEX, VALS(sccp_isni_iri_values), ANSI_ISNI_IRI_MASK,
2227 { &hf_sccp_ansi_isni_ti,
2228 { "ISNI Type Indicator", "sccp.isni.ti",
2229 FT_UINT8, BASE_HEX, VALS(sccp_isni_ti_values), ANSI_ISNI_TI_MASK,
2231 { &hf_sccp_ansi_isni_netspec,
2232 { "ISNI Network Specific (Type 1)", "sccp.isni.netspec",
2233 FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_NETSPEC_MASK,
2235 { &hf_sccp_ansi_isni_counter,
2236 { "ISNI Counter", "sccp.isni.counter",
2237 FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_COUNTER_MASK,
2241 /* Setup protocol subtree array */
2242 static gint *ett[] = {
2245 &ett_sccp_called_ai,
2246 &ett_sccp_called_pc,
2247 &ett_sccp_called_gt,
2249 &ett_sccp_calling_ai,
2250 &ett_sccp_calling_pc,
2251 &ett_sccp_calling_gt,
2252 &ett_sccp_sequencing_segmenting,
2253 &ett_sccp_segmentation,
2254 &ett_sccp_ansi_isni_routing_control,
2257 /* Register the protocol name and description */
2258 proto_sccp = proto_register_protocol("Signalling Connection Control Part",
2261 /* Required function calls to register the header fields and subtrees used */
2262 proto_register_field_array(proto_sccp, hf, array_length(hf));
2263 proto_register_subtree_array(ett, array_length(ett));
2265 sccp_ssn_dissector_table = register_dissector_table("sccp.ssn", "SCCP SSN", FT_UINT8, BASE_DEC);
2270 proto_reg_handoff_sccp(void)
2272 dissector_handle_t sccp_handle;
2274 sccp_handle = create_dissector_handle(dissect_sccp, proto_sccp);
2276 dissector_add("mtp3.service_indicator", SCCP_SI, sccp_handle);
2277 dissector_add("m3ua.protocol_data_si", SCCP_SI, sccp_handle);
2279 data_handle = find_dissector("data");