* Routines for Signalling Connection Control Part (SCCP) dissection
*
* It is hopefully compliant to:
- * ANSI T1.112.3-1996
+ * ANSI T1.112.3-2001
* ITU-T Q.713 7/1996
* YDN 038-1997 (Chinese ITU variant)
* JT-Q713 and NTT-Q713 (Japan)
* Note that Japan-specific GTT is incomplete; in particular, the specific
* TTs that are defined in TTC and NTT are not decoded in detail.
*
- * Copyright 2002, Jeff Morriss <jeff.morriss[AT]ulticom.com>
+ * Copyright 2002, Jeff Morriss <jeff.morriss.ws [AT] gmail.com>
*
* $Id$
*
# include "config.h"
#endif
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <epan/packet.h>
-#include "packet-mtp3.h"
#include <epan/prefs.h>
#include <epan/emem.h>
#include <epan/reassemble.h>
+#include <epan/asn1.h>
+#include <epan/uat.h>
+#include <epan/strutil.h>
+#include <epan/expert.h>
+#include "packet-mtp3.h"
#include "packet-tcap.h"
#include "packet-sccp.h"
-#include "tap.h"
+#include "packet-e164.h"
+#include "packet-e212.h"
+#include "packet-frame.h"
+#include <epan/tap.h>
+#include <address.h>
+
+/* function prototypes */
+void proto_reg_handoff_sccp(void);
static Standard_Type decode_mtp3_standard;
+
#define SCCP_SI 3
#define SCCP_MSG_TYPE_OFFSET 0
#define POINTER_LENGTH 1
#define POINTER_LENGTH_LONG 2
+#define INVALID_LR 0xffffff /* a reserved value */
+
/* Same as below but with names typed out */
static const value_string sccp_message_type_values[] = {
- { SCCP_MSG_TYPE_CR, "Connection Request" },
- { SCCP_MSG_TYPE_CC, "Connection Confirm" },
- { SCCP_MSG_TYPE_CREF, "Connection Refused" },
- { SCCP_MSG_TYPE_RLSD, "Released" },
- { SCCP_MSG_TYPE_RLC, "Release Complete" },
- { SCCP_MSG_TYPE_DT1, "Data Form 1" },
- { SCCP_MSG_TYPE_DT2, "Data Form 2" },
- { SCCP_MSG_TYPE_AK, "Data Acknowledgement" },
- { SCCP_MSG_TYPE_UDT, "Unitdata" },
- { SCCP_MSG_TYPE_UDTS, "Unitdata Service" },
- { SCCP_MSG_TYPE_ED, "Expedited Data" },
- { SCCP_MSG_TYPE_EA, "Expedited Data Acknowledgement" },
- { SCCP_MSG_TYPE_RSR, "Reset Request" },
- { SCCP_MSG_TYPE_RSC, "Reset Confirmation" },
- { SCCP_MSG_TYPE_ERR, "Error" },
- { SCCP_MSG_TYPE_IT, "Inactivity Timer" },
- { SCCP_MSG_TYPE_XUDT, "Extended Unitdata" },
- { SCCP_MSG_TYPE_XUDTS, "Extended Unitdata Service" },
- { SCCP_MSG_TYPE_LUDT, "Long Unitdata (ITU)" },
- { SCCP_MSG_TYPE_LUDTS, "Long Unitdata Service (ITU)" },
- { 0, NULL } };
+ { SCCP_MSG_TYPE_CR, "Connection Request" },
+ { SCCP_MSG_TYPE_CC, "Connection Confirm" },
+ { SCCP_MSG_TYPE_CREF, "Connection Refused" },
+ { SCCP_MSG_TYPE_RLSD, "Released" },
+ { SCCP_MSG_TYPE_RLC, "Release Complete" },
+ { SCCP_MSG_TYPE_DT1, "Data Form 1" },
+ { SCCP_MSG_TYPE_DT2, "Data Form 2" },
+ { SCCP_MSG_TYPE_AK, "Data Acknowledgement" },
+ { SCCP_MSG_TYPE_UDT, "Unitdata" },
+ { SCCP_MSG_TYPE_UDTS, "Unitdata Service" },
+ { SCCP_MSG_TYPE_ED, "Expedited Data" },
+ { SCCP_MSG_TYPE_EA, "Expedited Data Acknowledgement" },
+ { SCCP_MSG_TYPE_RSR, "Reset Request" },
+ { SCCP_MSG_TYPE_RSC, "Reset Confirmation" },
+ { SCCP_MSG_TYPE_ERR, "Error" },
+ { SCCP_MSG_TYPE_IT, "Inactivity Timer" },
+ { SCCP_MSG_TYPE_XUDT, "Extended Unitdata" },
+ { SCCP_MSG_TYPE_XUDTS, "Extended Unitdata Service" },
+ { SCCP_MSG_TYPE_LUDT, "Long Unitdata" },
+ { SCCP_MSG_TYPE_LUDTS, "Long Unitdata Service" },
+ { 0, NULL } };
/* Same as above but in acronym form (for the Info column) */
const value_string sccp_message_type_acro_values[] = {
- { SCCP_MSG_TYPE_CR, "CR" },
- { SCCP_MSG_TYPE_CC, "CC" },
- { SCCP_MSG_TYPE_CREF, "CREF" },
- { SCCP_MSG_TYPE_RLSD, "RLSD" },
- { SCCP_MSG_TYPE_RLC, "RLC" },
- { SCCP_MSG_TYPE_DT1, "DT1" },
- { SCCP_MSG_TYPE_DT2, "DT2" },
- { SCCP_MSG_TYPE_AK, "AK" },
- { SCCP_MSG_TYPE_UDT, "UDT" },
- { SCCP_MSG_TYPE_UDTS, "UDTS" },
- { SCCP_MSG_TYPE_ED, "ED" },
- { SCCP_MSG_TYPE_EA, "EA" },
- { SCCP_MSG_TYPE_RSR, "RSR" },
- { SCCP_MSG_TYPE_RSC, "RSC" },
- { SCCP_MSG_TYPE_ERR, "ERR" },
- { SCCP_MSG_TYPE_IT, "IT" },
- { SCCP_MSG_TYPE_XUDT, "XUDT" },
- { SCCP_MSG_TYPE_XUDTS, "XUDTS" },
- { SCCP_MSG_TYPE_LUDT, "LUDT" },
- { SCCP_MSG_TYPE_LUDTS, "LUDTS" },
- { 0, NULL } };
-
-#define PARAMETER_LENGTH_LENGTH 1
-#define PARAMETER_LONG_DATA_LENGTH_LENGTH 2
-#define PARAMETER_TYPE_LENGTH 1
+ { SCCP_MSG_TYPE_CR, "CR" },
+ { SCCP_MSG_TYPE_CC, "CC" },
+ { SCCP_MSG_TYPE_CREF, "CREF" },
+ { SCCP_MSG_TYPE_RLSD, "RLSD" },
+ { SCCP_MSG_TYPE_RLC, "RLC" },
+ { SCCP_MSG_TYPE_DT1, "DT1" },
+ { SCCP_MSG_TYPE_DT2, "DT2" },
+ { SCCP_MSG_TYPE_AK, "AK" },
+ { SCCP_MSG_TYPE_UDT, "UDT" },
+ { SCCP_MSG_TYPE_UDTS, "UDTS" },
+ { SCCP_MSG_TYPE_ED, "ED" },
+ { SCCP_MSG_TYPE_EA, "EA" },
+ { SCCP_MSG_TYPE_RSR, "RSR" },
+ { SCCP_MSG_TYPE_RSC, "RSC" },
+ { SCCP_MSG_TYPE_ERR, "ERR" },
+ { SCCP_MSG_TYPE_IT, "IT" },
+ { SCCP_MSG_TYPE_XUDT, "XUDT" },
+ { SCCP_MSG_TYPE_XUDTS, "XUDTS" },
+ { SCCP_MSG_TYPE_LUDT, "LUDT" },
+ { SCCP_MSG_TYPE_LUDTS, "LUDTS" },
+ { 0, NULL } };
+
+#define PARAMETER_LENGTH_LENGTH 1
+#define PARAMETER_LONG_DATA_LENGTH_LENGTH 2
+#define PARAMETER_TYPE_LENGTH 1
#define PARAMETER_END_OF_OPTIONAL_PARAMETERS 0x00
#define PARAMETER_DESTINATION_LOCAL_REFERENCE 0x01
#define PARAMETER_DATA 0x0f
#define PARAMETER_SEGMENTATION 0x10
#define PARAMETER_HOP_COUNTER 0x11
-/* The below 2 are ITU only */
+/* Importance is ITU only */
#define PARAMETER_IMPORTANCE 0x12
#define PARAMETER_LONG_DATA 0x13
/* ISNI is ANSI only */
#define PARAMETER_ISNI 0xfa
static const value_string sccp_parameter_values[] = {
- { PARAMETER_END_OF_OPTIONAL_PARAMETERS, "End of Optional Parameters" },
- { PARAMETER_DESTINATION_LOCAL_REFERENCE, "Destination Local Reference" },
- { PARAMETER_SOURCE_LOCAL_REFERENCE, "Source Local Reference" },
- { PARAMETER_CALLED_PARTY_ADDRESS, "Called Party Address" },
- { PARAMETER_CALLING_PARTY_ADDRESS, "Calling Party Address" },
- { PARAMETER_CLASS, "Protocol Class" },
- { PARAMETER_SEGMENTING_REASSEMBLING, "Segmenting/Reassembling" },
- { PARAMETER_RECEIVE_SEQUENCE_NUMBER, "Receive Sequence Number" },
- { PARAMETER_SEQUENCING_SEGMENTING, "Sequencing/Segmenting" },
- { PARAMETER_CREDIT, "Credit" },
- { PARAMETER_RELEASE_CAUSE, "Release Cause" },
- { PARAMETER_RETURN_CAUSE, "Return Cause" },
- { PARAMETER_RESET_CAUSE, "Reset Cause" },
- { PARAMETER_ERROR_CAUSE, "Error Cause" },
- { PARAMETER_REFUSAL_CAUSE, "Refusal Cause" },
- { PARAMETER_DATA, "Data" },
- { PARAMETER_SEGMENTATION, "Segmentation" },
- { PARAMETER_HOP_COUNTER, "Hop Counter" },
- { PARAMETER_IMPORTANCE, "Importance (ITU)" },
- { PARAMETER_LONG_DATA, "Long Data (ITU)" },
- { PARAMETER_ISNI, "Intermediate Signaling Network Identification (ANSI)" },
- { 0, NULL } };
+ { PARAMETER_END_OF_OPTIONAL_PARAMETERS, "End of Optional Parameters" },
+ { PARAMETER_DESTINATION_LOCAL_REFERENCE, "Destination Local Reference" },
+ { PARAMETER_SOURCE_LOCAL_REFERENCE, "Source Local Reference" },
+ { PARAMETER_CALLED_PARTY_ADDRESS, "Called Party Address" },
+ { PARAMETER_CALLING_PARTY_ADDRESS, "Calling Party Address" },
+ { PARAMETER_CLASS, "Protocol Class" },
+ { PARAMETER_SEGMENTING_REASSEMBLING, "Segmenting/Reassembling" },
+ { PARAMETER_RECEIVE_SEQUENCE_NUMBER, "Receive Sequence Number" },
+ { PARAMETER_SEQUENCING_SEGMENTING, "Sequencing/Segmenting" },
+ { PARAMETER_CREDIT, "Credit" },
+ { PARAMETER_RELEASE_CAUSE, "Release Cause" },
+ { PARAMETER_RETURN_CAUSE, "Return Cause" },
+ { PARAMETER_RESET_CAUSE, "Reset Cause" },
+ { PARAMETER_ERROR_CAUSE, "Error Cause" },
+ { PARAMETER_REFUSAL_CAUSE, "Refusal Cause" },
+ { PARAMETER_DATA, "Data" },
+ { PARAMETER_SEGMENTATION, "Segmentation" },
+ { PARAMETER_HOP_COUNTER, "Hop Counter" },
+ { PARAMETER_IMPORTANCE, "Importance (ITU)" },
+ { PARAMETER_LONG_DATA, "Long Data" },
+ { PARAMETER_ISNI, "Intermediate Signaling Network Identification (ANSI)" },
+ { 0, NULL } };
#define END_OF_OPTIONAL_PARAMETERS_LENGTH 1
{ 0x1, "Address coded to National standard" },
{ 0, NULL } };
+#define ROUTE_ON_GT 0x0
+#define ROUTE_ON_SSN 0x1
+#define ROUTING_INDICATOR_SHIFT 6
static const value_string sccp_routing_indicator_values[] = {
- { 0x0, "Route on GT" },
- { 0x1, "Route on SSN" },
- { 0, NULL } };
-
-#define AI_GTI_NO_GT 0x0
-#define ITU_AI_GTI_NAI 0x1
-#define AI_GTI_TT 0x2
-#define ITU_AI_GTI_TT_NP_ES 0x3
+ { ROUTE_ON_GT, "Route on GT" },
+ { ROUTE_ON_SSN, "Route on SSN" },
+ { 0, NULL } };
+
+#define AI_GTI_NO_GT 0x0
+#define ITU_AI_GTI_NAI 0x1
+#define AI_GTI_TT 0x2
+#define ITU_AI_GTI_TT_NP_ES 0x3
#define ITU_AI_GTI_TT_NP_ES_NAI 0x4
static const value_string sccp_itu_global_title_indicator_values[] = {
{ AI_GTI_NO_GT, "No Global Title" },
{ 0x0, "SSN not present" },
{ 0, NULL } };
-#define ADDRESS_SSN_LENGTH 1
-#define INVALID_SSN 0xff
+#define ADDRESS_SSN_LENGTH 1
+#define INVALID_SSN 0xff
/* Some values from 3GPP TS 23.003 */
/* Japan TTC and NTT define a lot of SSNs, some of which conflict with
* these. They are not added for now.
* * * * * * * * * * * * * * * * */
#define GT_NAI_MASK 0x7F
#define GT_NAI_LENGTH 1
+#define GT_NAI_UNKNOWN 0x00
+#define GT_NAI_SUBSCRIBER_NUMBER 0x01
+#define GT_NAI_RESERVED_NATIONAL 0x02
+#define GT_NAI_NATIONAL_SIG_NUM 0x03
+#define GT_NAI_INTERNATIONAL_NUM 0x04
static const value_string sccp_nai_values[] = {
- { 0x00, "NAI unknown" },
- { 0x01, "Subscriber Number" },
- { 0x02, "Reserved for national use" },
- { 0x03, "National significant number" },
- { 0x04, "International number" },
- { 0, NULL } };
+ { GT_NAI_UNKNOWN, "NAI unknown" },
+ { GT_NAI_SUBSCRIBER_NUMBER, "Subscriber Number" },
+ { GT_NAI_RESERVED_NATIONAL, "Reserved for national use" },
+ { GT_NAI_NATIONAL_SIG_NUM, "National significant number" },
+ { GT_NAI_INTERNATIONAL_NUM, "International number" },
+ { 0, NULL } };
#define GT_OE_MASK 0x80
{ GT_OE_ODD, "Odd number of address signals" },
{ 0, NULL } };
-#define GT_SIGNAL_LENGTH 1
-#define GT_ODD_SIGNAL_MASK 0x0f
-#define GT_EVEN_SIGNAL_MASK 0xf0
-#define GT_EVEN_SIGNAL_SHIFT 4
-#define GT_MAX_SIGNALS (32*7) /* its a bit big, but it allows for adding a lot of "(spare)" and "Unknown" values (7 chars) if there are errors - e.g. ANSI vs ITU wrongly selected */
-static const value_string sccp_address_signal_values[] = {
+const value_string sccp_address_signal_values[] = {
{ 0, "0" },
{ 1, "1" },
{ 2, "2" },
/* * * * * * * * * * * * * * * * * * * * * * * * * *
* Global Title: ITU GTI == 0011, ANSI GTI == 0001 *
* * * * * * * * * * * * * * * * * * * * * * * * * */
-#define GT_NP_MASK 0xf0
-#define GT_NP_ES_LENGTH 1
+#define GT_NP_MASK 0xf0
+#define GT_NP_SHIFT 4
+#define GT_NP_ES_LENGTH 1
+#define GT_NP_UNKNOWN 0x00
+#define GT_NP_ISDN 0x01
+#define GT_NP_GENERIC_RESERVED 0x02
+#define GT_NP_DATA 0x03
+#define GT_NP_TELEX 0x04
+#define GT_NP_MARITIME_MOBILE 0x05
+#define GT_NP_LAND_MOBILE 0x06
+#define GT_NP_ISDN_MOBILE 0x07
+#define GT_NP_PRIVATE_NETWORK 0x0e
+#define GT_NP_RESERVED 0x0f
static const value_string sccp_np_values[] = {
- { 0x0, "Unknown" },
- { 0x1, "ISDN/telephony" },
- { 0x2, "Generic (ITU)/Reserved (ANSI)" },
- { 0x3, "Data" },
- { 0x4, "Telex" },
- { 0x5, "Maritime mobile" },
- { 0x6, "Land mobile" },
- { 0x7, "ISDN/mobile" },
- { 0xe, "Private network or network-specific" },
- { 0xf, "Reserved" },
- { 0, NULL } };
+ { GT_NP_UNKNOWN, "Unknown" },
+ { GT_NP_ISDN, "ISDN/telephony" },
+ { GT_NP_GENERIC_RESERVED, "Generic (ITU)/Reserved (ANSI)" },
+ { GT_NP_DATA, "Data" },
+ { GT_NP_TELEX, "Telex" },
+ { GT_NP_MARITIME_MOBILE, "Maritime mobile" },
+ { GT_NP_LAND_MOBILE, "Land mobile" },
+ { GT_NP_ISDN_MOBILE, "ISDN/mobile" },
+ { GT_NP_PRIVATE_NETWORK, "Private network or network-specific" },
+ { GT_NP_RESERVED, "Reserved" },
+ { 0, NULL } };
#define GT_ES_MASK 0x0f
#define GT_ES_UNKNOWN 0x0
/* Address signals above */
-#define CLASS_CLASS_MASK 0xf
-#define CLASS_SPARE_HANDLING_MASK 0xf0
+#define CLASS_CLASS_MASK 0xf
+#define CLASS_SPARE_HANDLING_MASK 0xf0
+#define CLASS_SPARE_HANDLING_SHIFT 4
static const value_string sccp_class_handling_values [] = {
{ 0x0, "No special options" },
{ 0x8, "Return message on error" },
{ 0, NULL } };
-#define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
-#define RSN_MASK 0xfe
+#define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
+#define RSN_MASK 0xfe
#define SEQUENCING_SEGMENTING_LENGTH 2
#define SEQUENCING_SEGMENTING_SSN_LENGTH 1
#define CREDIT_LENGTH 1
#define RELEASE_CAUSE_LENGTH 1
-static const value_string sccp_release_cause_values [] = {
+const value_string sccp_release_cause_values [] = {
{ 0x00, "End user originated" },
{ 0x01, "End user congestion" },
{ 0x02, "End user failure" },
{ 0x08, "Subsystem failure" },
{ 0x09, "Subsystem congestion" },
{ 0x0a, "MTP failure" },
- { 0x0b, "Netowrk congestion" },
+ { 0x0b, "Network congestion" },
{ 0x0c, "Expiration of reset timer" },
{ 0x0d, "Expiration of receive inactivity timer" },
{ 0x0e, "Reserved" },
#define RETURN_CAUSE_LENGTH 1
-static const value_string sccp_return_cause_values [] = {
+const value_string sccp_return_cause_values [] = {
{ 0x00, "No translation for an address of such nature" },
{ 0x01, "No translation for this specific address" },
{ 0x02, "Subsystem congestion" },
{ 0x0a, "Destination cannot perform reassembly" },
{ 0x0b, "SCCP failure" },
{ 0x0c, "Hop counter violation" },
- { 0x0d, "Segmentation not supported (ITU only)" },
- { 0x0e, "Segmentation failure (ITU only)" },
+ { 0x0d, "Segmentation not supported" },
+ { 0x0e, "Segmentation failure" },
+ { 0xf7, "Message change failure (ANSI only)" },
+ { 0xf8, "Invalid INS routing request (ANSI only)" },
{ 0xf9, "Invalid ISNI routing request (ANSI only)"},
{ 0xfa, "Unauthorized message (ANSI only)" },
{ 0xfb, "Message incompatibility (ANSI only)" },
{ 0xfc, "Cannot perform ISNI constrained routing (ANSI only)" },
- { 0xfd, "Unable to perform ISNI identification (ANSI only)" },
+ { 0xfd, "Redundant ISNI constrained routing (ANSI only)" },
+ { 0xfe, "Unable to perform ISNI identification (ANSI only)" },
{ 0, NULL } };
#define RESET_CAUSE_LENGTH 1
-static const value_string sccp_reset_cause_values [] = {
+const value_string sccp_reset_cause_values [] = {
{ 0x00, "End user originated" },
{ 0x01, "SCCP user originated" },
{ 0x02, "Message out of order - incorrect send sequence number" },
#define ERROR_CAUSE_LENGTH 1
-static const value_string sccp_error_cause_values [] = {
+const value_string sccp_error_cause_values [] = {
{ 0x00, "Local Reference Number (LRN) mismatch - unassigned destination LRN" },
{ 0x01, "Local Reference Number (LRN) mismatch - inconsistent source LRN" },
{ 0x02, "Point code mismatch" },
#define REFUSAL_CAUSE_LENGTH 1
-static const value_string sccp_refusal_cause_values [] = {
+const value_string sccp_refusal_cause_values [] = {
{ 0x00, "End user originated" },
{ 0x01, "End user congestion" },
{ 0x02, "End user failure" },
static int hf_sccp_variable_pointer2 = -1;
static int hf_sccp_variable_pointer3 = -1;
static int hf_sccp_optional_pointer = -1;
+static int hf_sccp_param_length = -1;
static int hf_sccp_ssn = -1;
static int hf_sccp_gt_digits = -1;
static int hf_sccp_called_gt_np = -1;
static int hf_sccp_called_gt_es = -1;
static int hf_sccp_called_gt_digits = -1;
+static int hf_sccp_called_gt_digits_length = -1;
/* Calling party address */
static int hf_sccp_calling_national_indicator = -1;
static int hf_sccp_calling_gt_np = -1;
static int hf_sccp_calling_gt_es = -1;
static int hf_sccp_calling_gt_digits = -1;
+static int hf_sccp_calling_gt_digits_length = -1;
/* Other parameter values */
static int hf_sccp_dlr = -1;
static int hf_sccp_ansi_isni_ti = -1;
static int hf_sccp_ansi_isni_netspec = -1;
static int hf_sccp_ansi_isni_counter = -1;
+static int hf_sccp_ansi_isni_network = -1;
+static int hf_sccp_ansi_isni_cluster = -1;
static int hf_sccp_xudt_msg_fragments = -1;
static int hf_sccp_xudt_msg_fragment = -1;
static int hf_sccp_xudt_msg_fragment_overlap = -1;
static int hf_sccp_xudt_msg_fragment_multiple_tails = -1;
static int hf_sccp_xudt_msg_fragment_too_long_fragment = -1;
static int hf_sccp_xudt_msg_fragment_error = -1;
+static int hf_sccp_xudt_msg_fragment_count = -1;
static int hf_sccp_xudt_msg_reassembled_in = -1;
+static int hf_sccp_xudt_msg_reassembled_length = -1;
static int hf_sccp_assoc_msg = -1;
static int hf_sccp_assoc_id = -1;
static gint ett_sccp_called_ai = -1;
static gint ett_sccp_called_pc = -1;
static gint ett_sccp_called_gt = -1;
+static gint ett_sccp_called_gt_digits = -1;
static gint ett_sccp_calling = -1;
static gint ett_sccp_calling_ai = -1;
static gint ett_sccp_calling_pc = -1;
static gint ett_sccp_calling_gt = -1;
+static gint ett_sccp_calling_gt_digits = -1;
static gint ett_sccp_sequencing_segmenting = -1;
static gint ett_sccp_segmentation = -1;
static gint ett_sccp_ansi_isni_routing_control = -1;
/* Declarations to desegment XUDT Messages */
static gboolean sccp_xudt_desegment = TRUE;
-
static gboolean show_key_params = FALSE;
+static gboolean set_addresses = FALSE;
static int sccp_tap = -1;
&hf_sccp_xudt_msg_fragment_multiple_tails,
&hf_sccp_xudt_msg_fragment_too_long_fragment,
&hf_sccp_xudt_msg_fragment_error,
+ &hf_sccp_xudt_msg_fragment_count,
/* Reassembled in field */
&hf_sccp_xudt_msg_reassembled_in,
+ /* Reassembled length field */
+ &hf_sccp_xudt_msg_reassembled_length,
/* Tag */
"SCCP XUDT Message fragments"
};
static GHashTable *sccp_xudt_msg_reassembled_table = NULL;
+#define SCCP_USER_DATA 0
+#define SCCP_USER_TCAP 1
+#define SCCP_USER_RANAP 2
+#define SCCP_USER_BSSAP 3
+#define SCCP_USER_GSMMAP 4
+#define SCCP_USER_CAMEL 5
+#define SCCP_USER_INAP 6
+
+typedef struct _sccp_user_t {
+ guint ni;
+ range_t* called_pc;
+ range_t* called_ssn;
+ guint user;
+ gboolean uses_tcap;
+ dissector_handle_t* handlep;
+} sccp_user_t;
+
+static sccp_user_t* sccp_users;
+static guint num_sccp_users;
+
+static dissector_handle_t data_handle;
+static dissector_handle_t tcap_handle;
+static dissector_handle_t ranap_handle;
+static dissector_handle_t bssap_handle;
+static dissector_handle_t gsmmap_handle;
+static dissector_handle_t camel_handle;
+static dissector_handle_t inap_handle;
+static dissector_handle_t default_handle;
+
+static const char *default_payload=NULL;
+
+static const value_string sccp_users_vals[] = {
+ { SCCP_USER_DATA, "Data"},
+ { SCCP_USER_TCAP, "TCAP"},
+ { SCCP_USER_RANAP, "RANAP"},
+ { SCCP_USER_BSSAP, "BSSAP"},
+ { SCCP_USER_GSMMAP, "GSM MAP"},
+ { SCCP_USER_CAMEL, "CAMEL"},
+ { SCCP_USER_INAP, "INAP"},
+ { 0, NULL }
+};
/*
* Here are the global variables associated with
static guint dlr = 0;
static guint slr = 0;
-static dissector_handle_t data_handle;
static dissector_table_t sccp_ssn_dissector_table;
static emem_tree_t* assocs = NULL;
static sccp_assoc_info_t* assoc;
-static sccp_assoc_info_t no_assoc = {0,0,0,0,0,FALSE,FALSE,NULL,NULL,SCCP_PLOAD_NONE,NULL,NULL,NULL};
+static sccp_msg_info_t* sccp_msg;
+static sccp_assoc_info_t no_assoc = {0,0,0,0,0,FALSE,FALSE,NULL,NULL,SCCP_PLOAD_NONE,NULL,NULL,NULL,0};
static gboolean trace_sccp = FALSE;
static guint32 next_assoc_id = 0;
static const value_string assoc_protos[] = {
- { SCCP_PLOAD_BSSAP, "BSSAP" },
- { SCCP_PLOAD_RANAP, "RANAP" },
- { 0 , NULL }
+ { SCCP_PLOAD_BSSAP, "BSSAP" },
+ { SCCP_PLOAD_RANAP, "RANAP" },
+ { 0, NULL }
};
-static sccp_assoc_info_t* new_assoc(guint32 calling, guint32 called){
- sccp_assoc_info_t* a = se_alloc(sizeof(sccp_assoc_info_t));
+static sccp_assoc_info_t *
+new_assoc(guint32 calling, guint32 called)
+{
+ sccp_assoc_info_t* a = se_alloc0(sizeof(sccp_assoc_info_t));
a->id = next_assoc_id++;
a->calling_dpc = calling;
a->called_dpc = called;
a->calling_ssn = INVALID_SSN;
a->called_ssn = INVALID_SSN;
- a->has_fw_key = FALSE;
- a->has_bw_key = FALSE;
+ a->msgs = NULL;
+ a->curr_msg = NULL;
a->payload = SCCP_PLOAD_NONE;
a->calling_party = NULL;
a->called_party = NULL;
a->extra_info = NULL;
- a->msgs = NULL;
return a;
}
-sccp_assoc_info_t* get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_lr, guint32 dst_lr, guint msg_type) {
+void
+reset_sccp_assoc(void)
+{
+ assoc = NULL;
+}
+
+sccp_assoc_info_t *
+get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_lr, guint32 dst_lr, guint msg_type)
+{
guint32 opck, dpck;
address* opc = &(pinfo->src);
address* dpc = &(pinfo->dst);
guint framenum = pinfo->fd->num;
- if (assoc)
- return assoc;
+ if(assoc)
+ return assoc;
- if (!src_lr && !dst_lr){
- return &no_assoc;
- }
-
- opck = opc->type == AT_SS7PC ? mtp3_pc_hash(opc->data) : g_str_hash(address_to_str(opc));
- dpck = dpc->type == AT_SS7PC ? mtp3_pc_hash(dpc->data) : g_str_hash(address_to_str(dpc));
+ opck = opc->type == AT_SS7PC ? mtp3_pc_hash((const mtp3_addr_pc_t *)opc->data) : g_str_hash(ep_address_to_str(opc));
+ dpck = dpc->type == AT_SS7PC ? mtp3_pc_hash((const mtp3_addr_pc_t *)dpc->data) : g_str_hash(ep_address_to_str(dpc));
switch (msg_type) {
- case SCCP_MSG_TYPE_CR:
- {
- /* CR contains the opc,dpc,dlr key of backward messages swapped as dpc,opc,slr */
- emem_tree_key_t bw_key[] = {
- {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL}
- };
-
- if (! ( assoc = se_tree_lookup32_array(assocs,bw_key) ) && ! pinfo->fd->flags.visited ) {
- assoc = new_assoc(opck,dpck);
- se_tree_insert32_array(assocs,bw_key,assoc);
- assoc->has_bw_key = TRUE;
- }
- break;
- }
- case SCCP_MSG_TYPE_CC:
- {
- emem_tree_key_t fw_key[] = {
- {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL}
- };
- emem_tree_key_t bw_key[] = {
- {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
- };
-
- if ( ( assoc = se_tree_lookup32_array(assocs,bw_key) ) ) {
- goto got_assoc;
- }
-
- if ( (assoc = se_tree_lookup32_array(assocs,fw_key) ) ) {
- goto got_assoc;
- }
-
- assoc = new_assoc(opck,dpck);
-
- got_assoc:
- if ( ! pinfo->fd->flags.visited && ! assoc->has_bw_key ) {
-
- se_tree_insert32_array(assocs,bw_key,assoc);
- assoc->has_bw_key = TRUE;
- }
-
- if ( ! pinfo->fd->flags.visited && ! assoc->has_fw_key ) {
- se_tree_insert32_array(assocs,fw_key,assoc);
- assoc->has_fw_key = TRUE;
- }
-
- break;
- }
- default:
- {
- emem_tree_key_t key[] = {
- {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
- };
-
- assoc = se_tree_lookup32_array(assocs,key);
-
- break;
- }
+ case SCCP_MSG_TYPE_CR:
+ {
+ /* CR contains the opc,dpc,dlr key of backward messages swapped as dpc,opc,slr */
+ emem_tree_key_t bw_key[] = {
+ {1, &dpck},
+ {1, &opck},
+ {1, &src_lr},
+ {0, NULL}
+ };
+
+ if (! ( assoc = se_tree_lookup32_array(assocs,bw_key) ) && ! pinfo->fd->flags.visited ) {
+ assoc = new_assoc(opck, dpck);
+ se_tree_insert32_array(assocs, bw_key, assoc);
+ assoc->has_bw_key = TRUE;
+ }
+
+ pinfo->p2p_dir = P2P_DIR_SENT;
+
+ break;
+ }
+ case SCCP_MSG_TYPE_CC:
+ {
+ emem_tree_key_t fw_key[] = {
+ {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL}
+ };
+ emem_tree_key_t bw_key[] = {
+ {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
+ };
+
+ if ( ( assoc = se_tree_lookup32_array(assocs, bw_key) ) ) {
+ goto got_assoc;
+ }
+
+ if ( (assoc = se_tree_lookup32_array(assocs, fw_key) ) ) {
+ goto got_assoc;
+ }
+
+ assoc = new_assoc(dpck,opck);
+
+ got_assoc:
+
+ pinfo->p2p_dir = P2P_DIR_RECV;
+
+ if ( ! pinfo->fd->flags.visited && ! assoc->has_bw_key ) {
+ se_tree_insert32_array(assocs, bw_key, assoc);
+ assoc->has_bw_key = TRUE;
+ }
+
+ if ( ! pinfo->fd->flags.visited && ! assoc->has_fw_key ) {
+ se_tree_insert32_array(assocs, fw_key, assoc);
+ assoc->has_fw_key = TRUE;
+ }
+
+ break;
+ }
+ case SCCP_MSG_TYPE_RLC:
+ {
+ emem_tree_key_t bw_key[] = {
+ {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL}
+ };
+ emem_tree_key_t fw_key[] = {
+ {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
+ };
+ if ( ( assoc = se_tree_lookup32_array(assocs, bw_key) ) ) {
+ goto got_assoc_rlc;
+ }
+
+ if ( (assoc = se_tree_lookup32_array(assocs, fw_key) ) ) {
+ goto got_assoc_rlc;
+ }
+
+ assoc = new_assoc(dpck, opck);
+
+ got_assoc_rlc:
+
+ pinfo->p2p_dir = P2P_DIR_SENT;
+
+ if ( ! pinfo->fd->flags.visited && ! assoc->has_bw_key ) {
+ se_tree_insert32_array(assocs, bw_key, assoc);
+ assoc->has_bw_key = TRUE;
+ }
+
+ if ( ! pinfo->fd->flags.visited && ! assoc->has_fw_key ) {
+ se_tree_insert32_array(assocs, fw_key, assoc);
+ assoc->has_fw_key = TRUE;
+ }
+ break;
+ }
+ default:
+ {
+ emem_tree_key_t key[] = {
+ {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
+ };
+
+ assoc = se_tree_lookup32_array(assocs, key);
+
+ if (assoc) {
+ if (assoc->calling_dpc == dpck) {
+ pinfo->p2p_dir = P2P_DIR_RECV;
+ } else {
+ pinfo->p2p_dir = P2P_DIR_SENT;
+ }
+ }
+
+ break;
+ }
}
- if (assoc && trace_sccp) {
- if ( ! pinfo->fd->flags.visited) {
- sccp_msg_info_t* msg = se_alloc(sizeof(sccp_msg_info_t));
- msg->framenum = framenum;
- msg->offset = offset;
- msg->next = NULL;
- msg->assoc = assoc;
- msg->label = NULL;
- msg->comment = NULL;
- msg->type = msg_type;
-
- if (assoc->msgs) {
- sccp_msg_info_t* m;
- for (m = assoc->msgs; m->next; m = m->next) ;
- m->next = msg;
- } else {
- assoc->msgs = msg;
- }
-
- assoc->curr_msg = msg;
-
- } else {
-
- sccp_msg_info_t* m;
-
- for (m = assoc->msgs; m; m = m->next) {
- if (m->framenum == framenum && m->offset == offset) {
- assoc->curr_msg = m;
- break;
- }
- }
- }
- }
+ if (assoc && trace_sccp) {
+ if ( ! pinfo->fd->flags.visited) {
+ sccp_msg_info_t* msg = se_alloc0(sizeof(sccp_msg_info_t));
+ msg->framenum = framenum;
+ msg->offset = offset;
+ msg->data.co.next = NULL;
+ msg->data.co.assoc = assoc;
+ msg->data.co.label = NULL;
+ msg->data.co.comment = NULL;
+ msg->type = msg_type;
+
+ if (assoc->msgs) {
+ sccp_msg_info_t* m;
+ for (m = assoc->msgs; m->data.co.next; m = m->data.co.next) ;
+ m->data.co.next = msg;
+ } else {
+ assoc->msgs = msg;
+ }
+
+ assoc->curr_msg = msg;
+
+ } else {
+
+ sccp_msg_info_t* m;
+
+ for (m = assoc->msgs; m; m = m->data.co.next) {
+ if (m->framenum == framenum && m->offset == offset) {
+ assoc->curr_msg = m;
+ break;
+ }
+ }
+ }
+ }
- return assoc ? assoc : &no_assoc;
+ return assoc ? assoc : &no_assoc;
}
message_length = tvb_length(message_tvb);
proto_tree_add_text(sccp_tree, message_tvb, 0, message_length,
- "Unknown message (%u byte%s)",
- message_length, plurality(message_length, "", "s"));
+ "Unknown message (%u byte%s)",
+ message_length, plurality(message_length, "", "s"));
}
static void
dissect_sccp_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint length)
{
proto_tree_add_text(tree, tvb, 0, length, "Unknown parameter 0x%x (%u byte%s)",
- type, length, plurality(length, "", "s"));
+ type, length, plurality(length, "", "s"));
}
static void
-dissect_sccp_dlr_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
+dissect_sccp_dlr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
- proto_item* lr_item;
+ proto_item *lr_item, *expert_item;
+
+ if (length != 3) {
+ expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 3, got %u", length);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 3, got %u", length);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
dlr = tvb_get_letoh24(tvb, 0);
proto_tree_add_uint(tree, hf_sccp_dlr, tvb, 0, length, dlr);
lr_item = proto_tree_add_uint(tree, hf_sccp_lr, tvb, 0, length, dlr);
PROTO_ITEM_SET_HIDDEN(lr_item);
- if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+ if (show_key_params)
col_append_fstr(pinfo->cinfo, COL_INFO, "DLR=%d ", dlr);
}
static void
-dissect_sccp_slr_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
+dissect_sccp_slr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
- proto_item* lr_item;
+ proto_item *lr_item, *expert_item;
+
+ if (length != 3) {
+ expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 3, got %u", length);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 3, got %u", length);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
slr = tvb_get_letoh24(tvb, 0);
proto_tree_add_uint(tree, hf_sccp_slr, tvb, 0, length, slr);
lr_item = proto_tree_add_uint(tree, hf_sccp_lr, tvb, 0, length, slr);
PROTO_ITEM_SET_HIDDEN(lr_item);
- if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+ if (show_key_params)
col_append_fstr(pinfo->cinfo, COL_INFO, "SLR=%d ", slr);
}
-static void
-dissect_sccp_gt_address_information(tvbuff_t *tvb, proto_tree *tree,
- guint length, gboolean even_length,
- gboolean called)
+
+#define is_connectionless(m) \
+ ( m == SCCP_MSG_TYPE_UDT || m == SCCP_MSG_TYPE_UDTS \
+ || m == SCCP_MSG_TYPE_XUDT|| m == SCCP_MSG_TYPE_XUDTS \
+ || m == SCCP_MSG_TYPE_LUDT|| m == SCCP_MSG_TYPE_LUDTS)
+
+static proto_tree *
+dissect_sccp_gt_address_information(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint length,
+ gboolean even_length, gboolean called,
+ gboolean route_on_gt)
{
guint offset = 0;
- guint8 odd_signal, even_signal = 0x0f;
- char gt_digits[GT_MAX_SIGNALS+1] = { 0 };
+ guint8 odd_signal, even_signal;
+ proto_item *digits_item;
+ proto_tree *digits_tree;
+ char *gt_digits;
- while(offset < length)
- {
+ gt_digits = ep_alloc0(GT_MAX_SIGNALS+1);
+
+ while(offset < length) {
odd_signal = tvb_get_guint8(tvb, offset) & GT_ODD_SIGNAL_MASK;
even_signal = tvb_get_guint8(tvb, offset) & GT_EVEN_SIGNAL_MASK;
even_signal >>= GT_EVEN_SIGNAL_SHIFT;
- strncat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values,
- "Unknown"), GT_MAX_SIGNALS - strlen(gt_digits));
+ g_strlcat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values,
+ "Unknown: %d"), GT_MAX_SIGNALS+1);
/* If the last signal is NOT filler */
if (offset != (length - 1) || even_length == TRUE)
- strncat(gt_digits, val_to_str(even_signal, sccp_address_signal_values,
- "Unknown"), GT_MAX_SIGNALS - strlen(gt_digits));
+ g_strlcat(gt_digits, val_to_str(even_signal, sccp_address_signal_values,
+ "Unknown: %d"), GT_MAX_SIGNALS+1);
offset += GT_SIGNAL_LENGTH;
}
- proto_tree_add_string_format(tree, called ? hf_sccp_called_gt_digits
- : hf_sccp_calling_gt_digits,
- tvb, 0, length, gt_digits,
- "Address information (digits): %s", gt_digits);
- proto_tree_add_string_hidden(tree, called ? hf_sccp_gt_digits
- : hf_sccp_gt_digits,
- tvb, 0, length, gt_digits);
+ if (is_connectionless(message_type) && sccp_msg) {
+ guint8** gt_ptr = called ? &(sccp_msg->data.ud.called_gt) : &(sccp_msg->data.ud.calling_gt);
+
+ *gt_ptr = (guint8 *)ep_strdup(gt_digits);
+ }
+
+ digits_item = proto_tree_add_string(tree, called ? hf_sccp_called_gt_digits
+ : hf_sccp_calling_gt_digits,
+ tvb, 0, length, gt_digits);
+ digits_tree = proto_item_add_subtree(digits_item, called ? ett_sccp_called_gt_digits
+ : ett_sccp_calling_gt_digits);
+
+ if (set_addresses && route_on_gt) {
+ if (called) {
+ SET_ADDRESS(&pinfo->dst, AT_STRINGZ, 1+(int)strlen(gt_digits), gt_digits);
+ } else {
+ SET_ADDRESS(&pinfo->src, AT_STRINGZ, 1+(int)strlen(gt_digits), gt_digits);
+ }
+ }
+
+ proto_tree_add_string(digits_tree, hf_sccp_gt_digits, tvb, 0, length, gt_digits);
+ proto_tree_add_uint(digits_tree, called ? hf_sccp_called_gt_digits_length
+ : hf_sccp_calling_gt_digits_length,
+ tvb, 0, length, (guint32)strlen(gt_digits));
+
+ return digits_tree;
}
static void
-dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint length,
- guint8 gti, gboolean called)
+dissect_sccp_global_title(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length,
+ guint8 gti, gboolean route_on_gt, gboolean called)
{
- proto_item *gt_item = 0;
- proto_tree *gt_tree = 0;
+ proto_item *gt_item;
+ proto_tree *gt_tree;
+ proto_tree *digits_tree;
tvbuff_t *signals_tvb;
guint offset = 0;
- guint8 odd_even, nai, tt, np, es;
+ guint8 odd_even, nai = 0, np = 0, es;
gboolean even = TRUE;
/* Shift GTI to where we can work with it */
: ett_sccp_calling_gt);
/* Decode Transation Type (if present) */
- switch (gti) {
- case AI_GTI_TT:
-
- /* Protocol doesn't tell us, so we ASSUME even... */
- even = TRUE;
- /* Fall through */
- case ITU_AI_GTI_TT_NP_ES:
- case ITU_AI_GTI_TT_NP_ES_NAI:
- case ANSI_AI_GTI_TT_NP_ES:
+ if ((gti == AI_GTI_TT) ||
+ (decode_mtp3_standard != ANSI_STANDARD &&
+ (gti == ITU_AI_GTI_TT_NP_ES || gti == ITU_AI_GTI_TT_NP_ES_NAI)) ||
+ (decode_mtp3_standard == ANSI_STANDARD && gti == ANSI_AI_GTI_TT_NP_ES)) {
- tt = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_tt
+ proto_tree_add_item(gt_tree, called ? hf_sccp_called_gt_tt
: hf_sccp_calling_gt_tt,
- tvb, offset, GT_TT_LENGTH, tt);
+ tvb, offset, GT_TT_LENGTH, ENC_NA);
offset += GT_TT_LENGTH;
}
+ if (gti == AI_GTI_TT) {
+ /* Protocol doesn't tell us, so we ASSUME even... */
+ even = TRUE;
+ }
+
/* Decode Numbering Plan and Encoding Scheme (if present) */
- switch (gti) {
- case ITU_AI_GTI_TT_NP_ES:
- case ITU_AI_GTI_TT_NP_ES_NAI:
- case ANSI_AI_GTI_TT_NP_ES:
+ if ((decode_mtp3_standard != ANSI_STANDARD &&
+ (gti == ITU_AI_GTI_TT_NP_ES || gti == ITU_AI_GTI_TT_NP_ES_NAI)) ||
+ (decode_mtp3_standard == ANSI_STANDARD && gti == ANSI_AI_GTI_TT_NP_ES)) {
np = tvb_get_guint8(tvb, offset) & GT_NP_MASK;
proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_np
offset += GT_NP_ES_LENGTH;
}
- /* Decode Odd/Even Indicator (if present) */
- if (gti == ITU_AI_GTI_NAI) {
- odd_even = tvb_get_guint8(tvb, offset) & GT_OE_MASK;
- proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_oe
- : hf_sccp_calling_gt_oe,
- tvb, offset, GT_NAI_LENGTH, odd_even);
- even = (odd_even == GT_OE_EVEN) ? TRUE : FALSE;
-
- /* offset doesn't change */
- }
-
/* Decode Nature of Address Indicator (if present) */
- switch (gti) {
- case ITU_AI_GTI_NAI:
- case ITU_AI_GTI_TT_NP_ES_NAI:
+ if (decode_mtp3_standard != ANSI_STANDARD &&
+ (gti == ITU_AI_GTI_NAI || gti == ITU_AI_GTI_TT_NP_ES_NAI)) {
+
+ /* Decode Odd/Even Indicator (if present) */
+ if (gti == ITU_AI_GTI_NAI) {
+ odd_even = tvb_get_guint8(tvb, offset) & GT_OE_MASK;
+ proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_oe
+ : hf_sccp_calling_gt_oe,
+ tvb, offset, GT_NAI_LENGTH, odd_even);
+ even = (odd_even == GT_OE_EVEN) ? TRUE : FALSE;
+ }
+
nai = tvb_get_guint8(tvb, offset) & GT_NAI_MASK;
proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_nai
: hf_sccp_calling_gt_nai,
signals_tvb = tvb_new_subset(tvb, offset, (length - offset),
(length - offset));
- dissect_sccp_gt_address_information(signals_tvb, gt_tree, (length - offset),
- even, called);
+
+ digits_tree = dissect_sccp_gt_address_information(signals_tvb, pinfo, gt_tree,
+ (length - offset),
+ even, called, route_on_gt);
+
+ /* Display the country code (if we can) */
+ switch(np >> GT_NP_SHIFT) {
+ case GT_NP_ISDN:
+ case GT_NP_ISDN_MOBILE:
+ if(nai == GT_NAI_INTERNATIONAL_NUM) {
+ dissect_e164_cc(signals_tvb, digits_tree, 0, TRUE);
+ }
+ break;
+ case GT_NP_LAND_MOBILE:
+ dissect_e212_mcc_mnc_in_address(signals_tvb, pinfo, digits_tree, 0);
+ break;
+ default:
+ break;
+ }
}
static int
dissect_sccp_3byte_pc(tvbuff_t *tvb, proto_tree *call_tree, guint offset,
gboolean called)
{
- int *hf_pc;
+ int hf_pc;
if (decode_mtp3_standard == ANSI_STANDARD)
{
if (called)
- hf_pc = &hf_sccp_called_ansi_pc;
+ hf_pc = hf_sccp_called_ansi_pc;
else
- hf_pc = &hf_sccp_calling_ansi_pc;
+ hf_pc = hf_sccp_calling_ansi_pc;
} else /* CHINESE_ITU_STANDARD */ {
if (called)
- hf_pc = &hf_sccp_called_chinese_pc;
+ hf_pc = hf_sccp_called_chinese_pc;
else
- hf_pc = &hf_sccp_calling_chinese_pc;
+ hf_pc = hf_sccp_calling_chinese_pc;
}
/* create and fill the PC tree */
dissect_mtp3_3byte_pc(tvb, offset, call_tree,
called ? ett_sccp_called_pc : ett_sccp_calling_pc,
- *hf_pc,
+ hf_pc,
called ? hf_sccp_called_pc_network : hf_sccp_calling_pc_network,
called ? hf_sccp_called_pc_cluster : hf_sccp_calling_pc_cluster,
called ? hf_sccp_called_pc_member : hf_sccp_calling_pc_member,
* doing so does not appear to be very high.
*/
static void
-dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree,
+dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
guint length, gboolean called)
{
- proto_item *call_item = 0, *call_ai_item = 0, *item;
+ proto_item *call_item = 0, *call_ai_item = 0, *item, *hidden_item, *expert_item;
proto_tree *call_tree = 0, *call_ai_tree = 0;
guint offset;
- guint8 national = -1, routing_ind, gti, pci, ssni, ssn;
+ guint8 national = 0xFFU, routing_ind, gti, pci, ssni, ssn;
tvbuff_t *gt_tvb;
dissector_handle_t ssn_dissector = NULL, tcap_ssn_dissector = NULL;
const char *ssn_dissector_short_name = NULL;
const char *tcap_ssn_dissector_short_name = NULL;
call_item = proto_tree_add_text(tree, tvb, 0, length,
- "%s Party address (%u byte%s)",
- called ? "Called" : "Calling", length,
- plurality(length, "", "s"));
+ "%s Party address (%u byte%s)",
+ called ? "Called" : "Calling", length,
+ plurality(length, "", "s"));
call_tree = proto_item_add_subtree(call_item, called ? ett_sccp_called
: ett_sccp_calling);
call_ai_item = proto_tree_add_text(call_tree, tvb, 0,
- ADDRESS_INDICATOR_LENGTH,
- "Address Indicator");
+ ADDRESS_INDICATOR_LENGTH,
+ "Address Indicator");
call_ai_tree = proto_item_add_subtree(call_ai_item, called ? ett_sccp_called_ai
: ett_sccp_calling_ai);
if (decode_mtp3_standard == ANSI_STANDARD)
{
national = tvb_get_guint8(tvb, 0) & ANSI_NATIONAL_MASK;
- proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_national_indicator
- : hf_sccp_calling_national_indicator,
- tvb, 0, ADDRESS_INDICATOR_LENGTH, national);
+ expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_national_indicator
+ : hf_sccp_calling_national_indicator,
+ tvb, 0, ADDRESS_INDICATOR_LENGTH, national);
+ if (national == 0)
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_WARN, "Address is coded to "
+ "international standards. This doesn't normally happen in ANSI "
+ "networks.");
}
routing_ind = tvb_get_guint8(tvb, 0) & ROUTING_INDICATOR_MASK;
proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_routing_indicator
: hf_sccp_calling_routing_indicator,
tvb, 0, ADDRESS_INDICATOR_LENGTH, routing_ind);
+ /* Only shift off the other bits after adding the item */
+ routing_ind >>= ROUTING_INDICATOR_SHIFT;
gti = tvb_get_guint8(tvb, 0) & GTI_MASK;
national == 0) {
proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_global_title_indicator
- : hf_sccp_called_itu_global_title_indicator,
+ : hf_sccp_calling_itu_global_title_indicator,
tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
ssni = tvb_get_guint8(tvb, 0) & ITU_SSN_INDICATOR_MASK;
- proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_ssn_indicator
- : hf_sccp_calling_itu_ssn_indicator,
- tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
+ expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_ssn_indicator
+ : hf_sccp_calling_itu_ssn_indicator,
+ tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
+ if (routing_ind == ROUTE_ON_SSN && ssni == 0) {
+ expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN,
+ "Message is routed on SSN, but SSN is not present");
+ }
pci = tvb_get_guint8(tvb, 0) & ITU_PC_INDICATOR_MASK;
proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_point_code_indicator
/* Dissect PC (if present) */
if (pci) {
- if (decode_mtp3_standard == ITU_STANDARD) {
-
- proto_tree_add_item(call_tree, called ? hf_sccp_called_itu_pc
- : hf_sccp_calling_itu_pc,
- tvb, offset, ITU_PC_LENGTH, TRUE);
-
- offset += ITU_PC_LENGTH;
+ if (decode_mtp3_standard == ITU_STANDARD || national == 0) {
+ if (length < offset + ITU_PC_LENGTH){
+ expert_item = proto_tree_add_text(call_tree, tvb, 0, -1, "Wrong length indicated (%u) should be at least %u, PC is %u octets", length, offset + ITU_PC_LENGTH, ITU_PC_LENGTH);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated");
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
+ proto_tree_add_item(call_tree, called ? hf_sccp_called_itu_pc
+ : hf_sccp_calling_itu_pc,
+ tvb, offset, ITU_PC_LENGTH, ENC_LITTLE_ENDIAN);
+ offset += ITU_PC_LENGTH;
} else if (decode_mtp3_standard == JAPAN_STANDARD) {
- proto_tree_add_item(call_tree, called ? hf_sccp_called_japan_pc
- : hf_sccp_calling_japan_pc,
- tvb, offset, JAPAN_PC_LENGTH, TRUE);
+ if (length < offset + JAPAN_PC_LENGTH){
+ expert_item = proto_tree_add_text(call_tree, tvb, 0, -1, "Wrong length indicated (%u) should be at least %u, PC is %u octets", length, offset + JAPAN_PC_LENGTH, JAPAN_PC_LENGTH);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated");
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
+ proto_tree_add_item(call_tree, called ? hf_sccp_called_japan_pc
+ : hf_sccp_calling_japan_pc,
+ tvb, offset, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
- offset += JAPAN_PC_LENGTH;
+ offset += JAPAN_PC_LENGTH;
} else /* CHINESE_ITU_STANDARD */ {
- offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
+ if (length < offset + ANSI_PC_LENGTH){
+ expert_item = proto_tree_add_text(call_tree, tvb, 0, -1, "Wrong length indicated (%u) should be at least %u, PC is %u octets", length, offset + ANSI_PC_LENGTH, ANSI_PC_LENGTH);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated");
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
+ offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
}
}
if (ssni) {
ssn = tvb_get_guint8(tvb, offset);
+ if (routing_ind == ROUTE_ON_SSN && ssn == 0) {
+ expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN,
+ "Message is routed on SSN, but SSN is zero (unspecified)");
+ }
+
if (called && assoc)
assoc->called_ssn = ssn;
else if (assoc)
assoc->calling_ssn = ssn;
+ if (is_connectionless(message_type) && sccp_msg) {
+ guint *ssn_ptr = called ? &(sccp_msg->data.ud.called_ssn) : &(sccp_msg->data.ud.calling_ssn);
+
+ *ssn_ptr = ssn;
+ }
+
proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
: hf_sccp_calling_ssn,
tvb, offset, ADDRESS_SSN_LENGTH, ssn);
- proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
- ADDRESS_SSN_LENGTH, ssn);
+ hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset,
+ ADDRESS_SSN_LENGTH, ssn);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+
offset += ADDRESS_SSN_LENGTH;
/* Get the dissector handle of the dissector registered for this ssn
* And print it's name.
*/
- ssn_dissector = dissector_get_port_handle(sccp_ssn_dissector_table, ssn);
+ ssn_dissector = dissector_get_uint_handle(sccp_ssn_dissector_table, ssn);
if (ssn_dissector) {
- ssn_dissector_short_name = dissector_handle_get_short_name(ssn_dissector);
+ ssn_dissector_short_name = dissector_handle_get_short_name(ssn_dissector);
- if(ssn_dissector_short_name) {
- item = proto_tree_add_text(call_tree, tvb, offset - 1, ADDRESS_SSN_LENGTH, "Linked to %s", ssn_dissector_short_name);
- PROTO_ITEM_SET_GENERATED(item);
+ if(ssn_dissector_short_name) {
+ item = proto_tree_add_text(call_tree, tvb, offset - 1, ADDRESS_SSN_LENGTH, "Linked to %s", ssn_dissector_short_name);
+ PROTO_ITEM_SET_GENERATED(item);
- if (strncasecmp("TCAP", ssn_dissector_short_name, 4)== 0) {
- tcap_ssn_dissector = get_itu_tcap_subdissector(ssn);
+ if (g_ascii_strncasecmp("TCAP", ssn_dissector_short_name, 4)== 0) {
+ tcap_ssn_dissector = get_itu_tcap_subdissector(ssn);
- if(tcap_ssn_dissector){
- tcap_ssn_dissector_short_name = dissector_handle_get_short_name(tcap_ssn_dissector);
- proto_item_append_text(item,", TCAP SSN linked to %s", tcap_ssn_dissector_short_name);
- }
- }
- } /* short name */
+ if(tcap_ssn_dissector) {
+ tcap_ssn_dissector_short_name = dissector_handle_get_short_name(tcap_ssn_dissector);
+ proto_item_append_text(item,", TCAP SSN linked to %s", tcap_ssn_dissector_short_name);
+ }
+ }
+ } /* short name */
} /* ssn_dissector */
} /* ssni */
- if (!tree)
- return; /* got SSN, that's all we need here... */
-
/* Dissect GT (if present) */
if (gti != AI_GTI_NO_GT) {
if (length < offset)
gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
(length - offset));
- dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
- called);
+ dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti,
+ (routing_ind == ROUTE_ON_GT), called);
}
} else if (decode_mtp3_standard == ANSI_STANDARD) {
tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
ssni = tvb_get_guint8(tvb, 0) & ANSI_SSN_INDICATOR_MASK;
- proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator
- : hf_sccp_calling_ansi_ssn_indicator,
- tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
+ expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator
+ : hf_sccp_calling_ansi_ssn_indicator,
+ tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
+ if (routing_ind == ROUTE_ON_SSN && ssni == 0) {
+ expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN,
+ "Message is routed on SSN, but SSN is not present");
+ }
offset = ADDRESS_INDICATOR_LENGTH;
if (ssni) {
ssn = tvb_get_guint8(tvb, offset);
- if (called && assoc)
+ if (routing_ind == ROUTE_ON_SSN && ssn == 0) {
+ expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN,
+ "Message is routed on SSN, but SSN is zero (unspecified)");
+ }
+
+ if (called && assoc) {
assoc->called_ssn = ssn;
- else if (assoc)
+ } else if (assoc) {
assoc->calling_ssn = ssn;
+ }
+
+ if (is_connectionless(message_type) && sccp_msg) {
+ guint *ssn_ptr = called ? &(sccp_msg->data.ud.called_ssn) : &(sccp_msg->data.ud.calling_ssn);
+
+ *ssn_ptr = ssn;
+ }
proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
: hf_sccp_calling_ssn,
tvb, offset, ADDRESS_SSN_LENGTH, ssn);
- proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
- ADDRESS_SSN_LENGTH, ssn);
+ hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset,
+ ADDRESS_SSN_LENGTH, ssn);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+
offset += ADDRESS_SSN_LENGTH;
}
- if (!tree)
- return; /* got SSN, that's all we need here... */
-
/* Dissect PC (if present) */
if (pci) {
offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
/* Dissect GT (if present) */
if (gti != AI_GTI_NO_GT) {
if (length < offset)
- return;
+ return;
gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
(length - offset));
- dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
- called);
+ dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti,
+ (routing_ind == ROUTE_ON_GT), called);
}
}
}
static void
-dissect_sccp_called_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+dissect_sccp_called_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
- dissect_sccp_called_calling_param(tvb, tree, length, TRUE);
+ dissect_sccp_called_calling_param(tvb, tree, pinfo, length, TRUE);
}
static void
-dissect_sccp_calling_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+dissect_sccp_calling_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
- dissect_sccp_called_calling_param(tvb, tree, length, FALSE);
+ dissect_sccp_called_calling_param(tvb, tree, pinfo, length, FALSE);
}
static void
-dissect_sccp_class_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+dissect_sccp_class_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
- guint8 class, handling;
+ guint8 class;
+ proto_item *pi;
+ gboolean invalid_class = FALSE;
+
+ if (length != 1) {
+ pi = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
+ expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
+ PROTO_ITEM_SET_GENERATED(pi);
+ return;
+ }
class = tvb_get_guint8(tvb, 0) & CLASS_CLASS_MASK;
- handling = tvb_get_guint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK;
+ pi = proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, class);
+
+ switch(message_type) {
+ case SCCP_MSG_TYPE_DT1:
+ if (class != 2)
+ invalid_class = TRUE;
+ break;
+ case SCCP_MSG_TYPE_DT2:
+ case SCCP_MSG_TYPE_AK:
+ case SCCP_MSG_TYPE_ED:
+ case SCCP_MSG_TYPE_EA:
+ case SCCP_MSG_TYPE_RSR:
+ case SCCP_MSG_TYPE_RSC:
+ if (class != 3)
+ invalid_class = TRUE;
+ break;
+ case SCCP_MSG_TYPE_CR:
+ case SCCP_MSG_TYPE_CC:
+ case SCCP_MSG_TYPE_CREF:
+ case SCCP_MSG_TYPE_RLSD:
+ case SCCP_MSG_TYPE_RLC:
+ case SCCP_MSG_TYPE_ERR:
+ case SCCP_MSG_TYPE_IT:
+ if (class != 2 && class != 3)
+ invalid_class = TRUE;
+ break;
+ case SCCP_MSG_TYPE_UDT:
+ case SCCP_MSG_TYPE_UDTS:
+ case SCCP_MSG_TYPE_XUDT:
+ case SCCP_MSG_TYPE_XUDTS:
+ case SCCP_MSG_TYPE_LUDT:
+ case SCCP_MSG_TYPE_LUDTS:
+ if (class != 0 && class != 1)
+ invalid_class = TRUE;
+ break;
+ }
+
+ if (invalid_class)
+ expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "Unexpected message class for this message type");
+
+ if (class == 0 || class == 1) {
+ guint8 handling = tvb_get_guint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK;
- proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, class);
+ pi = proto_tree_add_item(tree, hf_sccp_handling, tvb, 0, length, ENC_NA);
+ handling >>= CLASS_SPARE_HANDLING_SHIFT;
- if (class == 0 || class == 1)
- proto_tree_add_uint(tree, hf_sccp_handling, tvb, 0, length, handling);
+ if (match_strval(handling, sccp_class_handling_values) == NULL) {
+ expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "Invalid message handling");
+ }
+ }
}
static void
-dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
- proto_tree_add_item(tree, hf_sccp_more, tvb, 0, length, FALSE);
+ if (length != 1) {
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
+
+ proto_tree_add_item(tree, hf_sccp_more, tvb, 0, length, ENC_BIG_ENDIAN);
}
static void
-dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
guint8 rsn;
+ if (length != 1) {
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
+
rsn = tvb_get_guint8(tvb, 0) >> 1;
proto_tree_add_uint(tree, hf_sccp_rsn, tvb, 0, length, rsn);
}
static void
dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
- guint8 rsn, ssn, more;
+ guint8 rsn, ssn;
proto_item *param_item;
proto_tree *param_tree;
ssn = tvb_get_guint8(tvb, 0) >> 1;
rsn = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) >> 1;
- more = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) & SEQUENCING_SEGMENTING_MORE_MASK;
- param_item = proto_tree_add_text(tree, tvb, 0, length,
+ param_item = proto_tree_add_text(tree, tvb, 0, length, "%s",
val_to_str(PARAMETER_SEQUENCING_SEGMENTING,
- sccp_parameter_values, "Unknown"));
+ sccp_parameter_values, "Unknown: %d"));
param_tree = proto_item_add_subtree(param_item,
ett_sccp_sequencing_segmenting);
proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_rsn, tvb,
SEQUENCING_SEGMENTING_SSN_LENGTH,
SEQUENCING_SEGMENTING_RSN_LENGTH, rsn);
- proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_more, tvb,
+ proto_tree_add_item(param_tree, hf_sccp_sequencing_segmenting_more, tvb,
SEQUENCING_SEGMENTING_SSN_LENGTH,
- SEQUENCING_SEGMENTING_RSN_LENGTH, more);
+ SEQUENCING_SEGMENTING_RSN_LENGTH, ENC_NA);
}
static void
-dissect_sccp_credit_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+dissect_sccp_credit_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
- guint8 credit;
+ if (length != 1) {
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
- credit = tvb_get_guint8(tvb, 0);
- proto_tree_add_uint(tree, hf_sccp_credit, tvb, 0, length, credit);
+ proto_tree_add_item(tree, hf_sccp_credit, tvb, 0, length, ENC_NA);
}
static void
-dissect_sccp_release_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
+dissect_sccp_release_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
guint8 cause;
+ if (length != 1) {
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
+
cause = tvb_get_guint8(tvb, 0);
proto_tree_add_uint(tree, hf_sccp_release_cause, tvb, 0, length, cause);
- if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+ if (show_key_params)
col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
}
static void
-dissect_sccp_return_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
+dissect_sccp_return_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
guint8 cause;
+ if (length != 1) {
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
+
cause = tvb_get_guint8(tvb, 0);
proto_tree_add_uint(tree, hf_sccp_return_cause, tvb, 0, length, cause);
- if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+ if (show_key_params)
col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
}
static void
-dissect_sccp_reset_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
+dissect_sccp_reset_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
guint8 cause;
+ if (length != 1) {
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
+
cause = tvb_get_guint8(tvb, 0);
proto_tree_add_uint(tree, hf_sccp_reset_cause, tvb, 0, length, cause);
- if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+ if (show_key_params)
col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
}
static void
-dissect_sccp_error_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
+dissect_sccp_error_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
guint8 cause;
+ if (length != 1) {
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
+
cause = tvb_get_guint8(tvb, 0);
proto_tree_add_uint(tree, hf_sccp_error_cause, tvb, 0, length, cause);
- if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+ if (show_key_params)
col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
}
static void
-dissect_sccp_refusal_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length, packet_info *pinfo)
+dissect_sccp_refusal_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
guint8 cause;
+ if (length != 1) {
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
+
cause = tvb_get_guint8(tvb, 0);
proto_tree_add_uint(tree, hf_sccp_refusal_cause, tvb, 0, length, cause);
- if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+ if (show_key_params)
col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
}
+
/* This function is used for both data and long data (ITU only) parameters */
static void
dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
guint8 ssn = INVALID_SSN;
guint8 other_ssn = INVALID_SSN;
+ const mtp3_addr_pc_t* dpc = NULL;
+ const mtp3_addr_pc_t* opc = NULL;
- if (trace_sccp && assoc && assoc != &no_assoc) {
- pinfo->sccp_info = assoc->curr_msg;
- } else {
- pinfo->sccp_info = NULL;
+ if (trace_sccp && assoc && assoc != &no_assoc) {
+ pinfo->sccp_info = assoc->curr_msg;
+ } else {
+ pinfo->sccp_info = NULL;
+ }
+
+ if (assoc) {
+ switch (pinfo->p2p_dir) {
+ case P2P_DIR_SENT:
+ ssn = assoc->calling_ssn;
+ other_ssn = assoc->called_ssn;
+ dpc = (const mtp3_addr_pc_t*)pinfo->dst.data;
+ opc = (const mtp3_addr_pc_t*)pinfo->src.data;
+ break;
+ case P2P_DIR_RECV:
+ ssn = assoc->called_ssn;
+ other_ssn = assoc->calling_ssn;
+ dpc = (const mtp3_addr_pc_t*)pinfo->src.data;
+ opc = (const mtp3_addr_pc_t*)pinfo->dst.data;
+ break;
+ default:
+ ssn = assoc->called_ssn;
+ other_ssn = assoc->calling_ssn;
+ dpc = (const mtp3_addr_pc_t*)pinfo->dst.data;
+ opc = (const mtp3_addr_pc_t*)pinfo->src.data;
+ break;
+ }
+ }
+
+
+ if (num_sccp_users && pinfo->src.type == AT_SS7PC) {
+ guint i;
+ dissector_handle_t handle = NULL;
+ gboolean uses_tcap = FALSE;
+
+ for (i=0; i < num_sccp_users; i++) {
+ sccp_user_t* u = &(sccp_users[i]);
+
+ if (!dpc || dpc->ni != u->ni) continue;
+
+ if (value_is_in_range(u->called_ssn, ssn) && value_is_in_range(u->called_pc, dpc->pc) ) {
+ handle = *(u->handlep);
+ uses_tcap = u->uses_tcap;
+ break;
+ } else if (value_is_in_range(u->called_ssn, other_ssn) && opc && value_is_in_range(u->called_pc, opc->pc) ) {
+ handle = *(u->handlep);
+ uses_tcap = u->uses_tcap;
+ break;
+ }
}
- if ( assoc ) {
- other_ssn = INVALID_SSN;
-
- switch (pinfo->p2p_dir) {
- case P2P_DIR_SENT:
- ssn = assoc->calling_ssn;
- break;
- case P2P_DIR_RECV:
- ssn = assoc->called_ssn;
- break;
- default:
- ssn = assoc->called_ssn;
- other_ssn = assoc->calling_ssn;
- break;
- }
+ if (handle) {
+ if (uses_tcap) {
+ call_tcap_dissector(handle, tvb, pinfo, tree);
+ } else {
+ call_dissector(handle, tvb, pinfo, tree);
+ }
+ return;
+ }
- } else {
- ssn = assoc->called_ssn;
- other_ssn = assoc->calling_ssn;
- }
+ }
- if (ssn != INVALID_SSN && dissector_try_port(sccp_ssn_dissector_table, ssn, tvb, pinfo, tree)) {
- return;
+ if (ssn != INVALID_SSN && dissector_try_uint(sccp_ssn_dissector_table, ssn, tvb, pinfo, tree)) {
+ return;
}
- if (other_ssn != INVALID_SSN && dissector_try_port(sccp_ssn_dissector_table, other_ssn, tvb, pinfo, tree)) {
- return;
+ if (other_ssn != INVALID_SSN && dissector_try_uint(sccp_ssn_dissector_table, other_ssn, tvb, pinfo, tree)) {
+ return;
}
/* try heuristic subdissector list to see if there are any takers */
if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree)) {
- return;
+ return;
+ }
+
+ /* try user default subdissector */
+ if (default_handle) {
+ call_dissector(default_handle, tvb, pinfo, tree);
+ return;
}
/* No sub-dissection occured, treat it as raw data */
}
static void
-dissect_sccp_segmentation_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+dissect_sccp_segmentation_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
- guint8 first, class, remaining;
- guint32 slr;
proto_item *param_item;
proto_tree *param_tree;
- first = tvb_get_guint8(tvb, 0) & SEGMENTATION_FIRST_SEGMENT_MASK;
- class = tvb_get_guint8(tvb, 0) & SEGMENTATION_CLASS_MASK;
- remaining = tvb_get_guint8(tvb, 0) & SEGMENTATION_REMAINING_MASK;
-
- slr = tvb_get_letoh24(tvb, 1);
-
- param_item = proto_tree_add_text(tree, tvb, 0, length,
+ param_item = proto_tree_add_text(tree, tvb, 0, length, "%s",
val_to_str(PARAMETER_SEGMENTATION,
- sccp_parameter_values, "Unknown"));
+ sccp_parameter_values, "Unknown: %d"));
param_tree = proto_item_add_subtree(param_item, ett_sccp_segmentation);
- proto_tree_add_uint(param_tree, hf_sccp_segmentation_first, tvb, 0, length,
- first);
- proto_tree_add_uint(param_tree, hf_sccp_segmentation_class, tvb, 0, length,
- class);
- proto_tree_add_uint(param_tree, hf_sccp_segmentation_remaining, tvb, 0,
- length, remaining);
- proto_tree_add_uint(param_tree, hf_sccp_segmentation_slr, tvb, 1, length,
- slr);
+ proto_tree_add_item(param_tree, hf_sccp_segmentation_first, tvb, 0, 1, ENC_NA);
+ proto_tree_add_item(param_tree, hf_sccp_segmentation_class, tvb, 0, 1, ENC_NA);
+ proto_tree_add_item(param_tree, hf_sccp_segmentation_remaining, tvb, 0, 1, ENC_NA);
+
+ if (length-1 != 3) {
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, length-1, "Wrong length indicated. Expected 3, got %u", length-1);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 3, got %u", length-1);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
+
+ proto_tree_add_item(param_tree, hf_sccp_segmentation_slr, tvb, 1, length-1, ENC_LITTLE_ENDIAN);
}
static void
}
static void
-dissect_sccp_importance_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+dissect_sccp_importance_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
{
- guint8 importance;
+ if (length != 1) {
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return;
+ }
- importance = tvb_get_guint8(tvb, 0) & IMPORTANCE_IMPORTANCE_MASK;
- proto_tree_add_uint(tree, hf_sccp_importance, tvb, 0, length, importance);
+ proto_tree_add_item(tree, hf_sccp_importance, tvb, 0, length, ENC_NA);
}
static void
dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
- guint8 mi, iri, ti, network, netspec;
+ guint8 ti;
guint offset = 0;
proto_item *param_item;
proto_tree *param_tree;
param_tree = proto_item_add_subtree(param_item,
ett_sccp_ansi_isni_routing_control);
- mi = tvb_get_guint8(tvb, offset) & ANSI_ISNI_MI_MASK;
- proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_mi, tvb, offset,
- ANSI_ISNI_ROUTING_CONTROL_LENGTH, mi);
+ proto_tree_add_item(param_tree, hf_sccp_ansi_isni_mi, tvb, offset,
+ ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA);
- iri = tvb_get_guint8(tvb, offset) & ANSI_ISNI_IRI_MASK;
- proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_iri, tvb, offset,
- ANSI_ISNI_ROUTING_CONTROL_LENGTH, iri);
+ proto_tree_add_item(param_tree, hf_sccp_ansi_isni_iri, tvb, offset,
+ ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA);
ti = tvb_get_guint8(tvb, offset) & ANSI_ISNI_TI_MASK;
proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_ti, tvb, offset,
ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
+ proto_tree_add_item(param_tree, hf_sccp_ansi_isni_counter, tvb, offset,
+ ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA);
+
offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
if ((ti >> ANSI_ISNI_TI_SHIFT) == ANSI_ISNI_TYPE_1) {
- netspec = tvb_get_guint8(tvb, offset) & ANSI_ISNI_NETSPEC_MASK;
proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_netspec, tvb, offset,
ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
while (offset < length) {
- network = tvb_get_guint8(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
- "Network ID network: %d", network);
+ proto_tree_add_item(tree, hf_sccp_ansi_isni_network, tvb, offset,
+ ANSI_NCM_LENGTH, ENC_NA);
offset++;
- network = tvb_get_guint8(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
- "Network ID cluster: %d", network);
+ proto_tree_add_item(tree, hf_sccp_ansi_isni_cluster, tvb, offset,
+ ANSI_NCM_LENGTH, ENC_NA);
offset++;
}
break;
case PARAMETER_DESTINATION_LOCAL_REFERENCE:
- dissect_sccp_dlr_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
+ dissect_sccp_dlr_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_SOURCE_LOCAL_REFERENCE:
- dissect_sccp_slr_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
+ dissect_sccp_slr_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_CALLED_PARTY_ADDRESS:
- dissect_sccp_called_param(parameter_tvb, sccp_tree, parameter_length);
+ dissect_sccp_called_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_CALLING_PARTY_ADDRESS:
- dissect_sccp_calling_param(parameter_tvb, sccp_tree, parameter_length);
+ dissect_sccp_calling_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_CLASS:
- dissect_sccp_class_param(parameter_tvb, sccp_tree, parameter_length);
+ dissect_sccp_class_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_SEGMENTING_REASSEMBLING:
- dissect_sccp_segmenting_reassembling_param(parameter_tvb, sccp_tree,
+ dissect_sccp_segmenting_reassembling_param(parameter_tvb, pinfo, sccp_tree,
parameter_length);
break;
case PARAMETER_RECEIVE_SEQUENCE_NUMBER:
- dissect_sccp_receive_sequence_number_param(parameter_tvb, sccp_tree,
+ dissect_sccp_receive_sequence_number_param(parameter_tvb, pinfo, sccp_tree,
parameter_length);
break;
break;
case PARAMETER_CREDIT:
- dissect_sccp_credit_param(parameter_tvb, sccp_tree, parameter_length);
+ dissect_sccp_credit_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_RELEASE_CAUSE:
- dissect_sccp_release_cause_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
+ dissect_sccp_release_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_RETURN_CAUSE:
- dissect_sccp_return_cause_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
+ dissect_sccp_return_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_RESET_CAUSE:
- dissect_sccp_reset_cause_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
+ dissect_sccp_reset_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_ERROR_CAUSE:
- dissect_sccp_error_cause_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
+ dissect_sccp_error_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_REFUSAL_CAUSE:
- dissect_sccp_refusal_cause_param(parameter_tvb, sccp_tree, parameter_length, pinfo);
+ dissect_sccp_refusal_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_DATA:
break;
case PARAMETER_SEGMENTATION:
- dissect_sccp_segmentation_param(parameter_tvb, sccp_tree, parameter_length);
+ dissect_sccp_segmentation_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
break;
case PARAMETER_HOP_COUNTER:
- dissect_sccp_hop_counter_param(parameter_tvb, sccp_tree, parameter_length);
+ dissect_sccp_hop_counter_param(parameter_tvb, sccp_tree, parameter_length);
break;
case PARAMETER_IMPORTANCE:
if (decode_mtp3_standard != ANSI_STANDARD)
- dissect_sccp_importance_param(parameter_tvb, sccp_tree, parameter_length);
+ dissect_sccp_importance_param(parameter_tvb, pinfo, sccp_tree, parameter_length);
else
- dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
+ dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
parameter_length);
break;
case PARAMETER_LONG_DATA:
- if (decode_mtp3_standard != ANSI_STANDARD)
- dissect_sccp_data_param(parameter_tvb, pinfo, tree);
- else
- dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
- parameter_length);
+ dissect_sccp_data_param(parameter_tvb, pinfo, tree);
break;
case PARAMETER_ISNI:
if (decode_mtp3_standard != ANSI_STANDARD)
- dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
+ dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
parameter_length);
else
- dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
+ dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
break;
default:
- dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
+ dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
parameter_length);
break;
}
{
guint16 parameter_length;
guint8 length_length;
+ proto_item *pi;
- if (parameter_type != PARAMETER_LONG_DATA)
- {
+ if (parameter_type != PARAMETER_LONG_DATA) {
parameter_length = tvb_get_guint8(tvb, offset);
length_length = PARAMETER_LENGTH_LENGTH;
- }
- else
- {
+ } else {
/* Long data parameter has 16 bit length */
parameter_length = tvb_get_letohs(tvb, offset);
length_length = PARAMETER_LONG_DATA_LENGTH_LENGTH;
}
- if (sccp_tree && sccp_show_length)
- {
- proto_tree_add_text(sccp_tree, tvb, offset, length_length,
- "%s length: %d",
- val_to_str(parameter_type, sccp_parameter_values,
- "Unknown"),
- parameter_length);
+ pi = proto_tree_add_uint_format(sccp_tree, hf_sccp_param_length, tvb, offset,
+ length_length, parameter_length, "%s length: %d",
+ val_to_str(parameter_type, sccp_parameter_values,
+ "Unknown: %d"),
+ parameter_length);
+ if (!sccp_show_length) {
+ /* The user doesn't want to see it... */
+ PROTO_ITEM_SET_HIDDEN(pi);
}
offset += length_length;
}
+static sccp_msg_info_t *
+new_ud_msg(packet_info* pinfo, guint32 msg_type _U_)
+{
+ sccp_msg_info_t* m = ep_alloc0(sizeof(sccp_msg_info_t));
+ m->framenum = pinfo->fd->num;
+ m->data.ud.calling_gt = NULL;
+ m->data.ud.called_gt = NULL;
+
+ register_frame_end_routine(reset_sccp_assoc);
+ return m;
+}
static void
dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
guint16 variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
guint16 optional_pointer = 0, orig_opt_ptr = 0;
guint16 offset = 0;
- guint8 parameter_type;
gboolean save_fragmented;
tvbuff_t *new_tvb = NULL;
fragment_data *frag_msg = NULL;
guint32 source_local_ref=0;
guint8 more;
- guint msg_offset = offset_from_real_beginning(tvb,0);
+ guint msg_offset = tvb_offset_from_real_beginning(tvb);
/* Macro for getting pointer to mandatory variable parameters */
#define VARIABLE_POINTER(var, hf_var, ptr_size) \
message_type = tvb_get_guint8(tvb, SCCP_MSG_TYPE_OFFSET);
offset = SCCP_MSG_TYPE_LENGTH;
- if (check_col(pinfo->cinfo, COL_INFO)) {
- col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
- val_to_str(message_type, sccp_message_type_acro_values, "Unknown"));
- };
+ /* Do not change col_add_fstr() to col_append_fstr() here: we _want_
+ * this call to overwrite whatever's currently in the INFO column (e.g.,
+ * "DATA" from the SCTP dissector).
+ *
+ * If there's something there that should not be overwritten, whoever
+ * put that info there should call col_set_fence() to protect it.
+ */
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(message_type, sccp_message_type_acro_values, "Unknown: %d"));
if (sccp_tree) {
/* add the message type to the protocol tree */
};
/* Starting a new message dissection; clear the global assoc, SLR, and DLR values */
- dlr = 0;
- slr = 0;
+ dlr = INVALID_LR;
+ slr = INVALID_LR;
assoc = NULL;
no_assoc.calling_dpc = 0;
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CLASS, offset,
PROTOCOL_CLASS_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
OPTIONAL_POINTER(POINTER_LENGTH)
PARAMETER_SOURCE_LOCAL_REFERENCE,
offset, SOURCE_LOCAL_REFERENCE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CLASS, offset,
offset,
DESTINATION_LOCAL_REFERENCE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_REFUSAL_CAUSE, offset,
PARAMETER_SOURCE_LOCAL_REFERENCE,
offset, SOURCE_LOCAL_REFERENCE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_RELEASE_CAUSE, offset,
RELEASE_CAUSE_LENGTH);
OPTIONAL_POINTER(POINTER_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
break;
case SCCP_MSG_TYPE_RLC:
PARAMETER_SOURCE_LOCAL_REFERENCE,
offset, SOURCE_LOCAL_REFERENCE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
-
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
break;
case SCCP_MSG_TYPE_DT1:
offset,
DESTINATION_LOCAL_REFERENCE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
more = tvb_get_guint8(tvb, offset) & SEGMENTING_REASSEMBLING_MASK;
offset, SEGMENTING_REASSEMBLING_LENGTH);
VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
- /* Reasemble */
+ /* Reassemble */
if (!sccp_xudt_desegment) {
proto_tree_add_text(sccp_tree, tvb, variable_pointer1,
tvb_get_guint8(tvb, variable_pointer1)+1,
save_fragmented = pinfo->fragmented;
pinfo->fragmented = TRUE;
frag_msg = fragment_add_seq_next(tvb, variable_pointer1 + 1, pinfo,
- source_local_ref, /* ID for fragments belonging together */
- sccp_xudt_msg_fragment_table, /* list of message fragments */
- sccp_xudt_msg_reassembled_table, /* list of reassembled messages */
- tvb_get_guint8(tvb,variable_pointer1),/* fragment length - to the end */
- more); /* More fragments? */
+ source_local_ref, /* ID for fragments belonging together */
+ sccp_xudt_msg_fragment_table, /* list of message fragments */
+ sccp_xudt_msg_reassembled_table, /* list of reassembled messages */
+ tvb_get_guint8(tvb,variable_pointer1), /* fragment length - to the end */
+ more); /* More fragments? */
new_tvb = process_reassembled_data(tvb, variable_pointer1 + 1, pinfo,
- "Reassembled Message", frag_msg,
+ "Reassembled SCCP", frag_msg,
&sccp_xudt_msg_frag_items, NULL,
tree);
if (frag_msg && frag_msg->next) { /* Reassembled */
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO,
- "(Message reassembled) ");
+ col_append_str(pinfo->cinfo, COL_INFO, "(Message reassembled) ");
} else if (more) { /* Not last packet of reassembled message */
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO, "(Message fragment) ");
+ col_append_str(pinfo->cinfo, COL_INFO, "(Message fragment) ");
}
pinfo->fragmented = save_fragmented;
offset,
DESTINATION_LOCAL_REFERENCE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_SEQUENCING_SEGMENTING, offset,
offset,
DESTINATION_LOCAL_REFERENCE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_RECEIVE_SEQUENCE_NUMBER,
break;
case SCCP_MSG_TYPE_UDT:
+ pinfo->sccp_info = sccp_msg = new_ud_msg(pinfo,message_type);
+
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CLASS, offset,
PROTOCOL_CLASS_LENGTH);
VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CALLED_PARTY_ADDRESS,
break;
case SCCP_MSG_TYPE_UDTS:
+ {
+ gboolean save_in_error_pkt = pinfo->in_error_pkt;
+ pinfo->in_error_pkt = TRUE;
+
+ pinfo->sccp_info = sccp_msg = new_ud_msg(pinfo,message_type);
+
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_RETURN_CAUSE, offset,
RETURN_CAUSE_LENGTH);
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
variable_pointer3);
+ pinfo->in_error_pkt = save_in_error_pkt;
break;
+ }
case SCCP_MSG_TYPE_ED:
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
offset,
DESTINATION_LOCAL_REFERENCE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH);
PARAMETER_DESTINATION_LOCAL_REFERENCE,
offset,
DESTINATION_LOCAL_REFERENCE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
-
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
break;
case SCCP_MSG_TYPE_RSR:
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_RESET_CAUSE, offset,
RESET_CAUSE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
break;
case SCCP_MSG_TYPE_RSC:
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_SOURCE_LOCAL_REFERENCE,
offset, SOURCE_LOCAL_REFERENCE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
break;
case SCCP_MSG_TYPE_ERR:
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_ERROR_CAUSE, offset,
ERROR_CAUSE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
break;
case SCCP_MSG_TYPE_IT:
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_SOURCE_LOCAL_REFERENCE,
offset, SOURCE_LOCAL_REFERENCE_LENGTH);
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CLASS, offset,
PROTOCOL_CLASS_LENGTH);
break;
case SCCP_MSG_TYPE_XUDT:
+ pinfo->sccp_info = sccp_msg = new_ud_msg(pinfo,message_type);
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CLASS, offset,
PROTOCOL_CLASS_LENGTH);
* message.
*/
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CALLED_PARTY_ADDRESS,
PARAMETER_CALLING_PARTY_ADDRESS,
variable_pointer2);
- if ((parameter_type = tvb_get_guint8(tvb, optional_pointer)) == PARAMETER_SEGMENTATION){
+ if (tvb_get_guint8(tvb, optional_pointer) == PARAMETER_SEGMENTATION) {
if (!sccp_xudt_desegment){
- proto_tree_add_text(sccp_tree, tvb, variable_pointer3, tvb_get_guint8(tvb, variable_pointer3)+1, "Segmented Data" );
-
+ proto_tree_add_text(sccp_tree, tvb, variable_pointer3, tvb_get_guint8(tvb, variable_pointer3)+1, "Segmented Data");
} else {
guint8 octet;
gboolean more_frag = TRUE;
-
/* Get the first octet of parameter Segmentation, Ch 3.17 in Q.713
* Bit 8 of octet 1 is used for First segment indication
* Bit 7 of octet 1 is used to keep in the message in sequence
save_fragmented = pinfo->fragmented;
pinfo->fragmented = TRUE;
frag_msg = fragment_add_seq_next(tvb, variable_pointer3 + 1, pinfo,
- source_local_ref, /* ID for fragments belonging together */
- sccp_xudt_msg_fragment_table, /* list of message fragments */
- sccp_xudt_msg_reassembled_table, /* list of reassembled messages */
- tvb_get_guint8(tvb,variable_pointer3), /* fragment length - to the end */
- more_frag); /* More fragments? */
+ source_local_ref, /* ID for fragments belonging together */
+ sccp_xudt_msg_fragment_table, /* list of message fragments */
+ sccp_xudt_msg_reassembled_table, /* list of reassembled messages */
+ tvb_get_guint8(tvb,variable_pointer3), /* fragment length - to the end */
+ more_frag); /* More fragments? */
if ((octet&0x80) == 0x80) /*First segment, set number of segments*/
fragment_set_tot_len(pinfo, source_local_ref, sccp_xudt_msg_fragment_table,(octet & 0xf));
new_tvb = process_reassembled_data(tvb, variable_pointer3 + 1,
- pinfo, "Reassembled Message",
+ pinfo, "Reassembled SCCP",
frag_msg,
&sccp_xudt_msg_frag_items,
NULL, tree);
if (frag_msg) { /* Reassembled */
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO,
- "(Message reassembled) ");
+ col_append_str(pinfo->cinfo, COL_INFO,"(Message reassembled) ");
} else { /* Not last packet of reassembled message */
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO,
- "(Message fragment) ");
+ col_append_str(pinfo->cinfo, COL_INFO,"(Message fragment) ");
}
pinfo->fragmented = save_fragmented;
break;
case SCCP_MSG_TYPE_XUDTS:
+ {
+ gboolean save_in_error_pkt = pinfo->in_error_pkt;
+ pinfo->in_error_pkt = TRUE;
+
+ pinfo->sccp_info = sccp_msg = new_ud_msg(pinfo,message_type);
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_RETURN_CAUSE, offset,
RETURN_CAUSE_LENGTH);
VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
OPTIONAL_POINTER(POINTER_LENGTH)
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CALLED_PARTY_ADDRESS,
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CALLING_PARTY_ADDRESS,
variable_pointer2);
- dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
- variable_pointer3);
- break;
+ if (tvb_get_guint8(tvb, optional_pointer) == PARAMETER_SEGMENTATION) {
+ if (!sccp_xudt_desegment){
+ proto_tree_add_text(sccp_tree, tvb, variable_pointer3, tvb_get_guint8(tvb, variable_pointer3)+1, "Segmented Data");
+
+ } else {
+ guint8 octet;
+ gboolean more_frag = TRUE;
+
+
+ /* Get the first octet of parameter Segmentation, Ch 3.17 in Q.713
+ * Bit 8 of octet 1 is used for First segment indication
+ * Bit 7 of octet 1 is used to keep in the message in sequence
+ * delivery option required by the SCCP user
+ * Bits 6 and 5 in octet 1 are spare bits.
+ * Bits 4-1 of octet 1 are used to indicate the number of
+ * remaining segments.
+ * The values 0000 to 1111 are possible; the value 0000 indicates
+ * the last segment.
+ */
+ octet = tvb_get_guint8(tvb,optional_pointer+2);
+ source_local_ref = tvb_get_letoh24(tvb, optional_pointer+3);
+
+ if ((octet&0x0f) == 0)
+ more_frag = FALSE;
+
+ save_fragmented = pinfo->fragmented;
+ pinfo->fragmented = TRUE;
+ frag_msg = fragment_add_seq_next(tvb, variable_pointer3 + 1, pinfo,
+ source_local_ref, /* ID for fragments belonging together */
+ sccp_xudt_msg_fragment_table, /* list of message fragments */
+ sccp_xudt_msg_reassembled_table, /* list of reassembled messages */
+ tvb_get_guint8(tvb,variable_pointer3), /* fragment length - to the end */
+ more_frag); /* More fragments? */
+
+ if ((octet&0x80) == 0x80) /*First segment, set number of segments*/
+ fragment_set_tot_len(pinfo, source_local_ref, sccp_xudt_msg_fragment_table,(octet & 0xf));
+
+ new_tvb = process_reassembled_data(tvb, variable_pointer3 + 1,
+ pinfo, "Reassembled SCCP",
+ frag_msg,
+ &sccp_xudt_msg_frag_items,
+ NULL, tree);
+
+ if (frag_msg) { /* Reassembled */
+ col_append_str(pinfo->cinfo, COL_INFO, "(Message reassembled) ");
+ } else { /* Not last packet of reassembled message */
+ col_append_str(pinfo->cinfo, COL_INFO, "(Message fragment) ");
+ }
+
+ pinfo->fragmented = save_fragmented;
+
+ if (new_tvb)
+ dissect_sccp_data_param(new_tvb, pinfo, tree);
+ }
+ } else {
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DATA, variable_pointer3);
+ }
+ pinfo->in_error_pkt = save_in_error_pkt;
+ break;
+ }
case SCCP_MSG_TYPE_LUDT:
- if (decode_mtp3_standard != ANSI_STANDARD)
- {
- offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
- PARAMETER_CLASS, offset,
- PROTOCOL_CLASS_LENGTH);
- offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
- PARAMETER_HOP_COUNTER, offset,
- HOP_COUNTER_LENGTH);
-
- VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
- VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
- VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
- OPTIONAL_POINTER(POINTER_LENGTH_LONG)
-
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
-
- dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
- PARAMETER_CALLED_PARTY_ADDRESS,
- variable_pointer1);
- dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
- PARAMETER_CALLING_PARTY_ADDRESS,
- variable_pointer2);
- dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
- PARAMETER_LONG_DATA, variable_pointer3);
- } else
- dissect_sccp_unknown_message(tvb, sccp_tree);
+ pinfo->sccp_info = sccp_msg = new_ud_msg(pinfo,message_type);
+
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CLASS, offset,
+ PROTOCOL_CLASS_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_HOP_COUNTER, offset,
+ HOP_COUNTER_LENGTH);
+
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
+ OPTIONAL_POINTER(POINTER_LENGTH_LONG)
+
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLED_PARTY_ADDRESS,
+ variable_pointer1);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLING_PARTY_ADDRESS,
+ variable_pointer2);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_LONG_DATA, variable_pointer3);
break;
case SCCP_MSG_TYPE_LUDTS:
- if (decode_mtp3_standard != ANSI_STANDARD)
- {
- offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
- PARAMETER_RETURN_CAUSE, offset,
- RETURN_CAUSE_LENGTH);
- offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
- PARAMETER_HOP_COUNTER, offset,
- HOP_COUNTER_LENGTH);
-
- VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
- VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
- VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
- OPTIONAL_POINTER(POINTER_LENGTH_LONG)
-
- assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
-
- dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
- PARAMETER_CALLED_PARTY_ADDRESS,
- variable_pointer1);
- dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
- PARAMETER_CALLING_PARTY_ADDRESS,
- variable_pointer2);
- dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
- PARAMETER_LONG_DATA, variable_pointer3);
- } else
- dissect_sccp_unknown_message(tvb, sccp_tree);
+ pinfo->sccp_info = sccp_msg = new_ud_msg(pinfo,message_type);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_RETURN_CAUSE, offset,
+ RETURN_CAUSE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_HOP_COUNTER, offset,
+ HOP_COUNTER_LENGTH);
+
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
+ OPTIONAL_POINTER(POINTER_LENGTH_LONG)
+
+ assoc = get_sccp_assoc(pinfo, msg_offset, slr, dlr, message_type);
+
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLED_PARTY_ADDRESS,
+ variable_pointer1);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLING_PARTY_ADDRESS,
+ variable_pointer2);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_LONG_DATA, variable_pointer3);
break;
default:
optional_pointer);
if (trace_sccp && assoc && assoc != &no_assoc) {
- proto_item* pi = proto_tree_add_uint(sccp_tree,hf_sccp_assoc_id,tvb,0,0,assoc->id);
- proto_tree* pt = proto_item_add_subtree(pi,ett_sccp_assoc);
+ proto_item *pi = proto_tree_add_uint(sccp_tree, hf_sccp_assoc_id, tvb, 0, 0, assoc->id);
+ proto_tree *pt = proto_item_add_subtree(pi, ett_sccp_assoc);
PROTO_ITEM_SET_GENERATED(pi);
if (assoc->msgs) {
sccp_msg_info_t* m;
- for(m = assoc->msgs; m ; m = m->next) {
- pi = proto_tree_add_uint( pt,hf_sccp_assoc_msg,tvb,0,0,m->framenum);
+ for(m = assoc->msgs; m ; m = m->data.co.next) {
+ pi = proto_tree_add_uint(pt, hf_sccp_assoc_msg, tvb, 0, 0, m->framenum);
if (assoc->payload != SCCP_PLOAD_NONE)
- proto_item_append_text(pi," %s", val_to_str(assoc->payload, assoc_protos, "Unknown"));
+ proto_item_append_text(pi," %s", val_to_str(assoc->payload, assoc_protos, "Unknown: %d"));
- if (m->label)
- proto_item_append_text(pi," %s", m->label);
+ if (m->data.co.label)
+ proto_item_append_text(pi," %s", m->data.co.label);
if (m->framenum == pinfo->fd->num && m->offset == msg_offset ) {
tap_queue_packet(sccp_tap, pinfo, m);
const mtp3_addr_pc_t *mtp3_addr_p;
if ((pinfo->src.type == AT_SS7PC) &&
- ((mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data)->type <= CHINESE_ITU_STANDARD))
- {
+ ((mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data)->type <= CHINESE_ITU_STANDARD)) {
/*
* Allow a protocol beneath to specify how the SCCP layer should be
* dissected.
* and at the same time ITU MTP3/ITU SCCP/ANSI TCAP/ANSI MAP.
*/
decode_mtp3_standard = mtp3_addr_p->type;
- }
- else
- {
+ } else {
decode_mtp3_standard = mtp3_standard;
}
/* Make entry in the Protocol column on summary display */
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- switch(decode_mtp3_standard) {
- case ITU_STANDARD:
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Int. ITU)");
- break;
- case ANSI_STANDARD:
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (ANSI)");
- break;
- case CHINESE_ITU_STANDARD:
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Chin. ITU)");
- break;
- case JAPAN_STANDARD:
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Japan)");
- break;
- };
+ switch(decode_mtp3_standard) {
+ case ITU_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Int. ITU)");
+ break;
+ case ANSI_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (ANSI)");
+ break;
+ case CHINESE_ITU_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Chin. ITU)");
+ break;
+ case JAPAN_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Japan)");
+ break;
+ };
/* In the interest of speed, if "tree" is NULL, don't do any work not
necessary to generate protocol tree items. */
if (tree) {
/* create the sccp protocol tree */
- sccp_item = proto_tree_add_item(tree, proto_sccp, tvb, 0, -1, FALSE);
+ sccp_item = proto_tree_add_item(tree, proto_sccp, tvb, 0, -1, ENC_NA);
sccp_tree = proto_item_add_subtree(sccp_item, ett_sccp);
}
/* Set whether message is UPLINK, DOWNLINK, or of UNKNOWN direction */
- if (pinfo->src.type == AT_SS7PC)
- {
+ if (pinfo->src.type == AT_SS7PC) {
/*
* XXX - we assume that the "data" pointers of the source and destination
* addresses are set to point to "mtp3_addr_pc_t" structures, so that
*/
mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data;
- if (sccp_source_pc_global == mtp3_addr_p->pc)
- {
+ if (sccp_source_pc_global == mtp3_addr_p->pc) {
pinfo->p2p_dir = P2P_DIR_SENT;
- }
- else
- {
+ } else {
/* assuming if src was SS7 PC then dst will be too */
mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->dst.data;
if (sccp_source_pc_global == mtp3_addr_p->pc)
{
pinfo->p2p_dir = P2P_DIR_RECV;
- }
- else
- {
+ } else {
pinfo->p2p_dir = P2P_DIR_UNKNOWN;
}
}
}
-static void init_sccp(void) {
+/*** SccpUsers Table **/
+
+static struct _sccp_ul {
+ guint id;
+ gboolean uses_tcap;
+ dissector_handle_t* handlep;
+ } user_list[] = {
+ {SCCP_USER_DATA, FALSE, &data_handle},
+ {SCCP_USER_TCAP, FALSE, &tcap_handle},
+ {SCCP_USER_RANAP, FALSE, &ranap_handle},
+ {SCCP_USER_BSSAP, FALSE, &bssap_handle},
+ {SCCP_USER_GSMMAP, TRUE, &gsmmap_handle},
+ {SCCP_USER_CAMEL, TRUE, &camel_handle},
+ {SCCP_USER_INAP, TRUE, &inap_handle},
+ {0, FALSE, NULL}
+};
+
+static void
+sccp_users_update_cb(void* r, const char** err _U_)
+{
+ sccp_user_t* u = r;
+ struct _sccp_ul* c;
+
+ for (c=user_list; c->handlep; c++) {
+ if (c->id == u->user) {
+ u->uses_tcap = c->uses_tcap;
+ u->handlep = c->handlep;
+ return;
+ }
+ }
+
+ u->uses_tcap = FALSE;
+ u->handlep = &data_handle;
+}
+
+static void *
+sccp_users_copy_cb(void* n, const void* o, size_t siz _U_)
+{
+ const sccp_user_t* u = o;
+ sccp_user_t* un = n;
+
+ un->ni = u->ni;
+ un->user = u->user;
+ un->uses_tcap = u->uses_tcap;
+ un->handlep = u->handlep;
+ if (u->called_pc) un->called_pc = range_copy(u->called_pc);
+ if (u->called_ssn) un->called_ssn = range_copy(u->called_ssn);
+
+ return n;
+}
+
+static void
+sccp_users_free_cb(void*r)
+{
+ sccp_user_t* u = r;
+ if (u->called_pc) g_free(u->called_pc);
+ if (u->called_ssn) g_free(u->called_ssn);
+}
+
+
+UAT_DEC_CB_DEF(sccp_users, ni, sccp_user_t)
+UAT_RANGE_CB_DEF(sccp_users, called_pc,sccp_user_t)
+UAT_RANGE_CB_DEF(sccp_users, called_ssn,sccp_user_t)
+UAT_VS_DEF(sccp_users, user, sccp_user_t, SCCP_USER_DATA, "Data")
+
+/** End SccpUsersTable **/
+
+
+static void
+init_sccp(void)
+{
next_assoc_id = 1;
fragment_table_init (&sccp_xudt_msg_fragment_table);
reassembled_table_init(&sccp_xudt_msg_reassembled_table);
{ &hf_sccp_message_type,
{ "Message Type", "sccp.message_type",
FT_UINT8, BASE_HEX, VALS(sccp_message_type_values), 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_variable_pointer1,
{ "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1",
FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_variable_pointer2,
{ "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2",
FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_variable_pointer3,
{ "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3",
FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_optional_pointer,
{ "Pointer to Optional parameter", "sccp.optional_pointer",
FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
+ { &hf_sccp_param_length,
+ { "Variable parameter length", "sccp.parameter_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
{ &hf_sccp_ssn,
{ "Called or Calling SubSystem Number", "sccp.ssn",
FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_gt_digits,
{ "Called or Calling GT Digits",
"sccp.digits",
FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_called_national_indicator,
{ "National Indicator", "sccp.called.ni",
FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_routing_indicator,
{ "Routing Indicator", "sccp.called.ri",
FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_itu_global_title_indicator,
{ "Global Title Indicator", "sccp.called.gti",
FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_ansi_global_title_indicator,
{ "Global Title Indicator", "sccp.called.gti",
FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_itu_ssn_indicator,
{ "SubSystem Number Indicator", "sccp.called.ssni",
FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_itu_point_code_indicator,
{ "Point Code Indicator", "sccp.called.pci",
FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_ansi_ssn_indicator,
{ "SubSystem Number Indicator", "sccp.called.ssni",
FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_ansi_point_code_indicator,
{ "Point Code Indicator", "sccp.called.pci",
FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_ssn,
{ "SubSystem Number", "sccp.called.ssn",
FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_itu_pc,
{ "PC", "sccp.called.pc",
FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_ansi_pc,
{ "PC", "sccp.called.ansi_pc",
FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_chinese_pc,
{ "PC", "sccp.called.chinese_pc",
FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_japan_pc,
{ "PC", "sccp.called.pc",
FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_called_pc_network,
{ "PC Network",
"sccp.called.network",
FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_called_pc_cluster,
{ "PC Cluster",
"sccp.called.cluster",
FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_called_pc_member,
{ "PC Member",
"sccp.called.member",
FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_called_gt_nai,
{ "Nature of Address Indicator",
"sccp.called.nai",
FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_called_gt_oe,
{ "Odd/Even Indicator",
"sccp.called.oe",
FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_called_gt_tt,
{ "Translation Type",
"sccp.called.tt",
FT_UINT8, BASE_HEX, NULL, 0x0,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_called_gt_np,
{ "Numbering Plan",
"sccp.called.np",
FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_called_gt_es,
{ "Encoding Scheme",
"sccp.called.es",
FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_called_gt_digits,
- { "GT Digits",
+ { "Called Party Digits",
"sccp.called.digits",
FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL }},
+ NULL, HFILL }},
+ { &hf_sccp_called_gt_digits_length,
+ { "Number of Called Party Digits",
+ "sccp.called.digits.length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
{ &hf_sccp_calling_national_indicator,
{ "National Indicator", "sccp.calling.ni",
FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_routing_indicator,
{ "Routing Indicator", "sccp.calling.ri",
FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_itu_global_title_indicator,
{ "Global Title Indicator", "sccp.calling.gti",
FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_ansi_global_title_indicator,
{ "Global Title Indicator", "sccp.calling.gti",
FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_itu_ssn_indicator,
{ "SubSystem Number Indicator", "sccp.calling.ssni",
FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_itu_point_code_indicator,
{ "Point Code Indicator", "sccp.calling.pci",
FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_ansi_ssn_indicator,
{ "SubSystem Number Indicator", "sccp.calling.ssni",
FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_ansi_point_code_indicator,
{ "Point Code Indicator", "sccp.calling.pci",
FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_ssn,
{ "SubSystem Number", "sccp.calling.ssn",
FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_itu_pc,
{ "PC", "sccp.calling.pc",
FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_ansi_pc,
{ "PC", "sccp.calling.ansi_pc",
FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_chinese_pc,
{ "PC", "sccp.calling.chinese_pc",
FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_japan_pc,
{ "PC", "sccp.calling.pc",
FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_calling_pc_network,
{ "PC Network",
"sccp.calling.network",
FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_calling_pc_cluster,
{ "PC Cluster",
"sccp.calling.cluster",
FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_calling_pc_member,
{ "PC Member",
"sccp.calling.member",
FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_calling_gt_nai,
{ "Nature of Address Indicator",
"sccp.calling.nai",
FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_calling_gt_oe,
{ "Odd/Even Indicator",
"sccp.calling.oe",
FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_calling_gt_tt,
{ "Translation Type",
"sccp.calling.tt",
FT_UINT8, BASE_HEX, NULL, 0x0,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_calling_gt_np,
{ "Numbering Plan",
"sccp.calling.np",
FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_calling_gt_es,
{ "Encoding Scheme",
"sccp.calling.es",
FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
- "", HFILL }},
+ NULL, HFILL }},
{ &hf_sccp_calling_gt_digits,
- { "GT Digits",
+ { "Calling Party Digits",
"sccp.calling.digits",
FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL }},
+ NULL, HFILL }},
+ { &hf_sccp_calling_gt_digits_length,
+ { "Number of Calling Party Digits",
+ "sccp.calling.digits.length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
{ &hf_sccp_dlr,
{ "Destination Local Reference", "sccp.dlr",
FT_UINT24, BASE_HEX, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_slr,
{ "Source Local Reference", "sccp.slr",
FT_UINT24, BASE_HEX, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_lr,
{ "Local Reference", "sccp.lr",
FT_UINT24, BASE_HEX, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_class,
{ "Class", "sccp.class",
FT_UINT8, BASE_HEX, NULL, CLASS_CLASS_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_handling,
{ "Message handling", "sccp.handling",
FT_UINT8, BASE_HEX, VALS(sccp_class_handling_values), CLASS_SPARE_HANDLING_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_more,
{ "More data", "sccp.more",
FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEGMENTING_REASSEMBLING_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_rsn,
{ "Receive Sequence Number", "sccp.rsn",
FT_UINT8, BASE_HEX, NULL, RSN_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_sequencing_segmenting_ssn,
{ "Sequencing Segmenting: Send Sequence Number", "sccp.sequencing_segmenting.ssn",
FT_UINT8, BASE_HEX, NULL, SEND_SEQUENCE_NUMBER_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_sequencing_segmenting_rsn,
{ "Sequencing Segmenting: Receive Sequence Number", "sccp.sequencing_segmenting.rsn",
FT_UINT8, BASE_HEX, NULL, RECEIVE_SEQUENCE_NUMBER_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_sequencing_segmenting_more,
{ "Sequencing Segmenting: More", "sccp.sequencing_segmenting.more",
FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEQUENCING_SEGMENTING_MORE_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_credit,
{ "Credit", "sccp.credit",
FT_UINT8, BASE_HEX, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_release_cause,
{ "Release Cause", "sccp.release_cause",
FT_UINT8, BASE_HEX, VALS(sccp_release_cause_values), 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_return_cause,
{ "Return Cause", "sccp.return_cause",
FT_UINT8, BASE_HEX, VALS(sccp_return_cause_values), 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_reset_cause,
{ "Reset Cause", "sccp.reset_cause",
FT_UINT8, BASE_HEX, VALS(sccp_reset_cause_values), 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_error_cause,
{ "Error Cause", "sccp.error_cause",
FT_UINT8, BASE_HEX, VALS(sccp_error_cause_values), 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_refusal_cause,
{ "Refusal Cause", "sccp.refusal_cause",
FT_UINT8, BASE_HEX, VALS(sccp_refusal_cause_values), 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_segmentation_first,
{ "Segmentation: First", "sccp.segmentation.first",
FT_UINT8, BASE_HEX, VALS(sccp_segmentation_first_segment_values), SEGMENTATION_FIRST_SEGMENT_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_segmentation_class,
{ "Segmentation: Class", "sccp.segmentation.class",
FT_UINT8, BASE_HEX, VALS(sccp_segmentation_class_values), SEGMENTATION_CLASS_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_segmentation_remaining,
{ "Segmentation: Remaining", "sccp.segmentation.remaining",
FT_UINT8, BASE_HEX, NULL, SEGMENTATION_REMAINING_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_segmentation_slr,
{ "Segmentation: Source Local Reference", "sccp.segmentation.slr",
FT_UINT24, BASE_HEX, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_hop_counter,
{ "Hop Counter", "sccp.hops",
FT_UINT8, BASE_HEX, NULL, 0x0,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_importance,
{ "Importance", "sccp.importance",
FT_UINT8, BASE_HEX, NULL, IMPORTANCE_IMPORTANCE_MASK,
- "", HFILL}},
+ NULL, HFILL}},
/* ISNI is ANSI only */
{ &hf_sccp_ansi_isni_mi,
{ "ISNI Mark for Identification Indicator", "sccp.isni.mi",
FT_UINT8, BASE_HEX, VALS(sccp_isni_mark_for_id_values), ANSI_ISNI_MI_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_ansi_isni_iri,
{ "ISNI Routing Indicator", "sccp.isni.iri",
FT_UINT8, BASE_HEX, VALS(sccp_isni_iri_values), ANSI_ISNI_IRI_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_ansi_isni_ti,
{ "ISNI Type Indicator", "sccp.isni.ti",
FT_UINT8, BASE_HEX, VALS(sccp_isni_ti_values), ANSI_ISNI_TI_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_ansi_isni_netspec,
{ "ISNI Network Specific (Type 1)", "sccp.isni.netspec",
FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_NETSPEC_MASK,
- "", HFILL}},
+ NULL, HFILL}},
{ &hf_sccp_ansi_isni_counter,
{ "ISNI Counter", "sccp.isni.counter",
- FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_COUNTER_MASK,
- "", HFILL}},
+ FT_UINT8, BASE_DEC, NULL, ANSI_ISNI_COUNTER_MASK,
+ NULL, HFILL}},
+ { &hf_sccp_ansi_isni_network,
+ { "Network ID network", "sccp.isni.network",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
+ { &hf_sccp_ansi_isni_cluster,
+ { "Network ID cluster", "sccp.isni.cluster",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_sccp_xudt_msg_fragments,
{"Message fragments", "sccp.msg.fragments",
FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }
},
{&hf_sccp_xudt_msg_fragment_overlap,
{"Message fragment overlap", "sccp.msg.fragment.overlap",
- FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }
},
{&hf_sccp_xudt_msg_fragment_overlap_conflicts,
{"Message fragment overlapping with conflicting data", "sccp.msg.fragment.overlap.conflicts",
- FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }
},
{&hf_sccp_xudt_msg_fragment_multiple_tails,
{"Message has multiple tail fragments", "sccp.msg.fragment.multiple_tails",
- FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }
},
{&hf_sccp_xudt_msg_fragment_too_long_fragment,
{"Message fragment too long", "sccp.msg.fragment.too_long_fragment",
- FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }
},
{&hf_sccp_xudt_msg_fragment_error,
{"Message defragmentation error", "sccp.msg.fragment.error",
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
},
+ {&hf_sccp_xudt_msg_fragment_count,
+ {"Message fragment count", "sccp.msg.fragment.count",
+ FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
+ },
{&hf_sccp_xudt_msg_reassembled_in,
{"Reassembled in", "sccp.msg.reassembled.in",
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
},
+ {&hf_sccp_xudt_msg_reassembled_length,
+ {"Reassembled SCCP length", "sccp.msg.reassembled.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
+ },
{ &hf_sccp_assoc_id,
{ "Association ID", "sccp.assoc.id",
- FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_sccp_assoc_msg,
{"Message in frame", "sccp.assoc.msg",
- FT_FRAMENUM, BASE_NONE, NULL, 0x00, "", HFILL }
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
},
};
&ett_sccp_called_ai,
&ett_sccp_called_pc,
&ett_sccp_called_gt,
+ &ett_sccp_called_gt_digits,
&ett_sccp_calling,
&ett_sccp_calling_ai,
&ett_sccp_calling_pc,
&ett_sccp_calling_gt,
+ &ett_sccp_calling_gt_digits,
&ett_sccp_sequencing_segmenting,
&ett_sccp_segmentation,
&ett_sccp_ansi_isni_routing_control,
&ett_sccp_assoc
};
- /* Register the protocol name and description */
+
+ static uat_field_t users_flds[] = {
+ UAT_FLD_DEC(sccp_users, ni, "Network Indicator", "Network Indicator"),
+ UAT_FLD_RANGE(sccp_users, called_pc, "Called DPCs", 0xFFFFFF, "DPCs for which this protocol is to be used"),
+ UAT_FLD_RANGE(sccp_users, called_ssn, "Called SSNs", 255, "Called SSNs for which this protocol is to be used"),
+ UAT_FLD_VS(sccp_users, user, "User protocol", sccp_users_vals, "The User Protocol"),
+ UAT_END_FIELDS
+ };
+
+
+ uat_t* users_uat = uat_new("SCCP Users Table", sizeof(sccp_user_t),
+ "sccp_users", TRUE, (void*) &sccp_users,
+ &num_sccp_users, UAT_CAT_PORTS, "ChSccpUsers",
+ sccp_users_copy_cb, sccp_users_update_cb,
+ sccp_users_free_cb, NULL, users_flds );
+
+ /* Register the protocol name and description */
proto_sccp = proto_register_protocol("Signalling Connection Control Part",
"SCCP", "sccp");
proto_register_field_array(proto_sccp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+
sccp_ssn_dissector_table = register_dissector_table("sccp.ssn", "SCCP SSN", FT_UINT8, BASE_DEC);
register_heur_dissector_list("sccp", &heur_subdissector_list);
- sccp_module = prefs_register_protocol(proto_sccp, NULL);
+ sccp_module = prefs_register_protocol(proto_sccp, proto_reg_handoff_sccp);
prefs_register_uint_preference(sccp_module, "source_pc",
- "Source PC",
+ "Source PC (in hex)",
"The source point code (usually MSC) (to determine whether message is uplink or downlink)",
16, &sccp_source_pc_global);
prefs_register_bool_preference(sccp_module, "trace_sccp",
"Trace Associations",
- "Whether to keep infomation about messages and their associations",
+ "Whether to keep information about messages and their associations",
&trace_sccp);
prefs_register_bool_preference(sccp_module, "show_more_info",
- "Show key parameters in Info Column",
- "Show SLR, DLR, and CAUSE Parameters in the Information Column of the Summary",
- &show_key_params);
+ "Show key parameters in Info Column",
+ "Show SLR, DLR, and CAUSE Parameters in the Information Column of the Summary",
+ &show_key_params);
+
+ prefs_register_uat_preference(sccp_module, "users_table", "Users Table",
+ "A table that enumerates user protocols to be used against specific PCs and SSNs",
+ users_uat);
+ prefs_register_bool_preference(sccp_module, "set_addresses", "Set source and destination GT addresses",
+ "Set the source and destination addresses to the GT digits (if RI=GT)."
+ " This may affect TCAP's ability to recognize which messages belong to which TCAP session.", &set_addresses);
+
+ prefs_register_string_preference(sccp_module, "default_payload", "Default Payload",
+ "The protocol which should be used to dissect the payload if nothing else has claimed it",
+ &default_payload);
register_init_routine(&init_sccp);
{
dissector_handle_t sccp_handle;
- sccp_handle = find_dissector("sccp");
+ static gboolean initialised=FALSE;
- dissector_add("mtp3.service_indicator", SCCP_SI, sccp_handle);
- dissector_add_string("tali.opcode", "sccp", sccp_handle);
+ if (!initialised) {
+ sccp_handle = find_dissector("sccp");
- data_handle = find_dissector("data");
-}
+ dissector_add_uint("wtap_encap", WTAP_ENCAP_SCCP, sccp_handle);
+ dissector_add_uint("mtp3.service_indicator", SCCP_SI, sccp_handle);
+ dissector_add_string("tali.opcode", "sccp", sccp_handle);
+
+ data_handle = find_dissector("data");
+ tcap_handle = find_dissector("tcap");
+ ranap_handle = find_dissector("ranap");
+ bssap_handle = find_dissector("bssap");
+ gsmmap_handle = find_dissector("gsm_map");
+ camel_handle = find_dissector("camel");
+ inap_handle = find_dissector("inap");
+ initialised = TRUE;
+ }
+
+ default_handle = find_dissector(default_payload);
+}