/* packet-sccp.c
* Routines for Signalling Connection Control Part (SCCP) dissection
+ *
* It is hopefully compliant to:
* ANSI T1.112.3-1996
* ITU-T Q.713 7/1996
+ * YDN 038-1997 (Chinese ITU variant)
*
* Copyright 2002, Jeff Morriss <jeff.morriss[AT]ulticom.com>
*
- * $Id: packet-sccp.c,v 1.6 2002/08/02 23:36:00 jmayer Exp $
+ * $Id: packet-sccp.c,v 1.20 2004/01/08 20:19:03 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
#include <stdio.h>
#include <stdlib.h>
-
#include <string.h>
-#include "epan/packet.h"
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+#include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
#include "packet-mtp3.h"
+#include "prefs.h"
#define SCCP_SI 3
#define MESSAGE_TYPE_OFFSET 0
#define MESSAGE_TYPE_LENGTH 1
#define POINTER_LENGTH 1
+#define POINTER_LENGTH_LONG 2
#define MESSAGE_TYPE_CR 0x01
#define MESSAGE_TYPE_CC 0x02
{ MESSAGE_TYPE_LUDTS, "Long Unitdata Service (ITU)" },
{ 0, NULL } };
-/* Same as above but in acronym for (for the Info column) */
+/* Same as above but in acronym form (for the Info column) */
static const value_string sccp_message_type_acro_values[] = {
{ MESSAGE_TYPE_CR, "CR" },
{ MESSAGE_TYPE_CC, "CC" },
{ 0x0c, "Reserved for international use (ITU only)" },
{ 0x0d, "Broadband ISDN edge-to-edge applications (ITU only)" },
{ 0x0e, "TC test responder (ITU only)" },
+ { 0x8e, "RANAP" },
+ { 0xfc, "IOS" },
+ { 0xfe, "BSSAP/BSAP" },
{ 0, NULL } };
static int hf_sccp_called_pc_member = -1;
static int hf_sccp_called_pc_cluster = -1;
static int hf_sccp_called_pc_network = -1;
+static int hf_sccp_called_ansi_pc = -1;
+static int hf_sccp_called_chinese_pc = -1;
static int hf_sccp_called_itu_pc = -1;
static int hf_sccp_called_gt_nai = -1;
static int hf_sccp_called_gt_oe = -1;
static int hf_sccp_calling_pc_member = -1;
static int hf_sccp_calling_pc_cluster = -1;
static int hf_sccp_calling_pc_network = -1;
+static int hf_sccp_calling_ansi_pc = -1;
+static int hf_sccp_calling_chinese_pc = -1;
static int hf_sccp_calling_itu_pc = -1;
static int hf_sccp_calling_gt_nai = -1;
static int hf_sccp_calling_gt_oe = -1;
static gint ett_sccp_segmentation = -1;
static gint ett_sccp_ansi_isni_routing_control = -1;
+/*
+ * Here are the global variables associated with
+ * the various user definable characteristics of the dissection
+ */
+static guint32 sccp_source_pc_global = 0;
+static gboolean sccp_show_length = FALSE;
+
+static module_t *sccp_module;
+static heur_dissector_list_t heur_subdissector_list;
/* Keep track of SSN value of current message so if/when we get to the data
* parameter, we can call appropriate sub-dissector. TODO: can this info
}
static void
-dissect_sccp_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint16 length)
+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"));
}
static void
-dissect_sccp_dlr_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_dlr_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint32 reference;
- reference = tvb_get_ntoh24(tvb, 0);
+ reference = tvb_get_letoh24(tvb, 0);
proto_tree_add_uint(tree, hf_sccp_dlr, tvb, 0, length, reference);
}
static void
-dissect_sccp_slr_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_slr_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint32 reference;
- reference = tvb_get_ntoh24(tvb, 0);
+ reference = tvb_get_letoh24(tvb, 0);
proto_tree_add_uint(tree, hf_sccp_slr, tvb, 0, length, reference);
}
static void
dissect_sccp_gt_address_information(tvbuff_t *tvb, proto_tree *tree,
- guint8 length, gboolean even_length,
+ guint length, gboolean even_length,
gboolean called)
{
- guint8 offset = 0;
+ guint offset = 0;
guint8 odd_signal, even_signal = 0x0f;
char gt_digits[GT_MAX_SIGNALS] = { 0 };
}
static void
-dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint8 length,
+dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint length,
guint8 gti, gboolean called)
{
proto_item *gt_item = 0;
proto_tree *gt_tree = 0;
tvbuff_t *signals_tvb;
- guint8 offset = 0;
+ guint offset = 0;
guint8 odd_even, nai, tt, np, es;
gboolean even = TRUE;
}
/* Decode address signal(s) */
+ if (length < offset)
+ return;
signals_tvb = tvb_new_subset(tvb, offset, (length - offset),
(length - offset));
dissect_sccp_gt_address_information(signals_tvb, gt_tree, (length - offset),
called);
}
+static int
+dissect_sccp_3byte_pc(tvbuff_t *tvb, proto_tree *call_tree, guint offset,
+ gboolean called)
+{
+ guint32 dpc;
+ proto_item *call_pc_item = 0;
+ proto_tree *call_pc_tree = 0;
+ char pc[ANSI_PC_STRING_LENGTH];
+ int *hf_pc;
+
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ if (called)
+ hf_pc = &hf_sccp_called_ansi_pc;
+ else
+ hf_pc = &hf_sccp_calling_ansi_pc;
+ } else /* CHINESE_ITU_STANDARD */ {
+ if (called)
+ hf_pc = &hf_sccp_called_chinese_pc;
+ else
+ hf_pc = &hf_sccp_calling_chinese_pc;
+ }
+
+ /* create the DPC tree; modified from that in packet-mtp3.c */
+ dpc = tvb_get_ntoh24(tvb, offset);
+ snprintf(pc, sizeof(pc), "%d-%d-%d", (dpc & ANSI_NETWORK_MASK),
+ ((dpc & ANSI_CLUSTER_MASK) >> 8),
+ ((dpc & ANSI_MEMBER_MASK) >> 16));
+
+ call_pc_item = proto_tree_add_string_format(call_tree, *hf_pc,
+ tvb, offset, ANSI_PC_LENGTH,
+ pc, "PC (%s)", pc);
+
+ call_pc_tree = proto_item_add_subtree(call_pc_item,
+ called ? ett_sccp_called_pc
+ : ett_sccp_calling_pc);
+
+ proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_member
+ : hf_sccp_calling_pc_member,
+ tvb, offset, ANSI_NCM_LENGTH, dpc);
+ offset += ANSI_NCM_LENGTH;
+ proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_cluster
+ : hf_sccp_calling_pc_cluster,
+ tvb, offset, ANSI_NCM_LENGTH, dpc);
+ offset += ANSI_NCM_LENGTH;
+ proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_network
+ : hf_sccp_calling_pc_network,
+ tvb, offset, ANSI_NCM_LENGTH, dpc);
+ offset += ANSI_NCM_LENGTH;
+
+ return(offset);
+}
+
/* FUNCTION dissect_sccp_called_calling_param():
* Dissect the Calling or Called Party Address parameters.
*
*/
static void
dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree,
- guint8 length, gboolean called)
+ guint length, gboolean called)
{
- proto_item *call_item = 0, *call_ai_item = 0, *call_pc_item = 0;
- proto_tree *call_tree = 0, *call_ai_tree = 0, *call_pc_tree = 0;
- guint8 offset;
+ proto_item *call_item = 0, *call_ai_item = 0;
+ proto_tree *call_tree = 0, *call_ai_tree = 0;
+ guint offset;
guint8 national = -1, routing_ind, gti, pci, ssni, ssn;
guint32 dpc;
tvbuff_t *gt_tvb;
gti = tvb_get_guint8(tvb, 0) & GTI_MASK;
- if (mtp3_standard == ITU_STANDARD || national == 0) {
+ if (mtp3_standard == ITU_STANDARD ||
+ mtp3_standard == CHINESE_ITU_STANDARD ||
+ national == 0) {
proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_global_title_indicator
: hf_sccp_called_itu_global_title_indicator,
/* Dissect PC (if present) */
if (pci) {
- dpc = tvb_get_letohs(tvb, offset) & ITU_PC_MASK;
- proto_tree_add_uint(call_tree, called ? hf_sccp_called_itu_pc
- : hf_sccp_calling_itu_pc,
- tvb, offset, ITU_PC_LENGTH, dpc);
- offset += ITU_PC_LENGTH;
+ if (mtp3_standard == ITU_STANDARD)
+ {
+
+ dpc = tvb_get_letohs(tvb, offset) & ITU_PC_MASK;
+ proto_tree_add_uint(call_tree, called ? hf_sccp_called_itu_pc
+ : hf_sccp_calling_itu_pc,
+ tvb, offset, ITU_PC_LENGTH, dpc);
+ offset += ITU_PC_LENGTH;
+
+ } else /* CHINESE_ITU_STANDARD */ {
+
+ offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
+
+ }
}
/* Dissect SSN (if present) */
/* Dissect GT (if present) */
if (gti != AI_GTI_NO_GT) {
+ if (length < offset)
+ return;
gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
(length - offset));
dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
/* Dissect PC (if present) */
if (pci) {
- /* create the DPC tree; modified from that in packet-mtp3.c */
- dpc = tvb_get_ntoh24(tvb, offset);
- call_pc_item = proto_tree_add_text(call_tree, tvb, offset,
- ANSI_PC_LENGTH,
- "PC (%d-%d-%d)",
- (dpc & ANSI_NETWORK_MASK),
- ((dpc & ANSI_CLUSTER_MASK) >> 8),
- ((dpc & ANSI_MEMBER_MASK) >> 16));
-
- call_pc_tree = proto_item_add_subtree(call_pc_item,
- called ? ett_sccp_called_pc
- : ett_sccp_calling_pc);
-
- proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_member
- : hf_sccp_calling_pc_member,
- tvb, offset, ANSI_NCM_LENGTH, dpc);
- offset += ANSI_NCM_LENGTH;
- proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_cluster
- : hf_sccp_calling_pc_cluster,
- tvb, offset, ANSI_NCM_LENGTH, dpc);
- offset += ANSI_NCM_LENGTH;
- proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_network
- : hf_sccp_calling_pc_network,
- tvb, offset, ANSI_NCM_LENGTH, dpc);
- offset += ANSI_NCM_LENGTH;
+ offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
}
/* Dissect GT (if present) */
if (gti != AI_GTI_NO_GT) {
+ if (length < offset)
+ return;
gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
(length - offset));
dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
}
static void
-dissect_sccp_called_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_called_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
dissect_sccp_called_calling_param(tvb, tree, length, TRUE);
}
static void
-dissect_sccp_calling_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_calling_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
dissect_sccp_called_calling_param(tvb, tree, length, FALSE);
}
static void
-dissect_sccp_class_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_class_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 class, handling;
}
static void
-dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 more;
}
static void
-dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 rsn;
}
static void
-dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 rsn, ssn, more;
proto_item *param_item;
}
static void
-dissect_sccp_credit_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_credit_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 credit;
}
static void
-dissect_sccp_release_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_release_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 cause;
}
static void
-dissect_sccp_return_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_return_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 cause;
}
static void
-dissect_sccp_reset_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_reset_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 cause;
}
static void
-dissect_sccp_error_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_error_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 cause;
}
static void
-dissect_sccp_refusal_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_refusal_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 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 *sccp_tree, proto_tree *tree)
+dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Try subdissectors (if we found a valid SSN on the current message) */
tree)))
return;
+ /* try heuristic subdissector list to see if there are any takers */
+ if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree))
+ {
+ return;
+ }
+
/* No sub-dissection occured, treat it as raw data */
- call_dissector(data_handle, tvb, pinfo, sccp_tree);
+ call_dissector(data_handle, tvb, pinfo, tree);
}
static void
-dissect_sccp_segmentation_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_segmentation_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 first, class, remaining;
guint32 slr;
class = tvb_get_guint8(tvb, 0) & SEGMENTATION_CLASS_MASK;
remaining = tvb_get_guint8(tvb, 0) & SEGMENTATION_REMAINING_MASK;
- slr = tvb_get_ntoh24(tvb, 1);
+ slr = tvb_get_letoh24(tvb, 1);
param_item = proto_tree_add_text(tree, tvb, 0, length,
val_to_str(PARAMETER_SEGMENTATION,
}
static void
-dissect_sccp_hop_counter_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_hop_counter_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 hops;
}
static void
-dissect_sccp_importance_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_importance_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 importance;
}
static void
-dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint length)
{
guint8 mi, iri, ti, network, netspec;
- guint8 offset = 0;
+ guint offset = 0;
proto_item *param_item;
proto_tree *param_tree;
*/
static guint16
dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
- proto_tree *tree, guint8 parameter_type, guint8 offset,
+ proto_tree *tree, guint8 parameter_type, guint16 offset,
guint16 parameter_length)
{
tvbuff_t *parameter_tvb;
break;
case PARAMETER_DATA:
- dissect_sccp_data_param(parameter_tvb, pinfo, sccp_tree, tree);
+ dissect_sccp_data_param(parameter_tvb, pinfo, tree);
/* TODO? Re-adjust length of SCCP item since it may be sub-dissected */
/* sccp_length = proto_item_get_len(sccp_item);
break;
case PARAMETER_IMPORTANCE:
- if (mtp3_standard == ITU_STANDARD)
+ if (mtp3_standard != ANSI_STANDARD)
dissect_sccp_importance_param(parameter_tvb, sccp_tree, parameter_length);
else
dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
break;
case PARAMETER_LONG_DATA:
- if (mtp3_standard == ITU_STANDARD)
- dissect_sccp_data_param(parameter_tvb, pinfo, sccp_tree, tree);
+ if (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);
break;
case PARAMETER_ISNI:
- if (mtp3_standard == ANSI_STANDARD)
- dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
- else
+ if (mtp3_standard != ANSI_STANDARD)
dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
parameter_length);
+ else
+ dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
break;
default:
static guint16
dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *sccp_tree, proto_tree *tree,
- guint8 parameter_type, guint8 offset)
+ guint8 parameter_type, guint16 offset)
{
guint16 parameter_length;
guint8 length_length;
else
{
/* Long data parameter has 16 bit length */
- parameter_length = tvb_get_ntohs(tvb, offset);
+ parameter_length = tvb_get_letohs(tvb, offset);
length_length = PARAMETER_LONG_DATA_LENGTH_LENGTH;
}
-/* TODO? I find this annoying, but it could possibly useful for debugging.
- * Make it a preference?
- * if (sccp_tree)
- * proto_tree_add_text(sccp_tree, tvb, offset, length_length,
- * "%s length: %d",
- * val_to_str(parameter_type, sccp_parameter_values,
- * "Unknown"),
- * parameter_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);
+ }
offset += length_length;
static void
dissect_sccp_optional_parameters(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *sccp_tree, proto_tree *tree,
- guint8 offset)
+ guint16 offset)
{
guint8 parameter_type;
proto_tree *tree)
{
guint8 message_type;
- guint8 variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
- guint8 optional_pointer = 0;
- guint8 offset = 0;
+ guint16 variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
+ guint16 optional_pointer = 0;
+ guint16 offset = 0;
/* Macro for getting pointer to mandatory variable parameters */
-#define VARIABLE_POINTER(var, hf_var) \
- var = tvb_get_guint8(tvb, offset); \
+#define VARIABLE_POINTER(var, hf_var, ptr_size) \
+ if (ptr_size == POINTER_LENGTH) \
+ var = tvb_get_guint8(tvb, offset); \
+ else \
+ var = tvb_get_letohs(tvb, offset); \
proto_tree_add_uint(sccp_tree, hf_var, tvb, \
- offset, POINTER_LENGTH, var); \
+ offset, ptr_size, var); \
var += offset; \
- offset += POINTER_LENGTH;
+ if (ptr_size == POINTER_LENGTH_LONG) \
+ var += 1; \
+ offset += ptr_size;
/* Macro for getting pointer to optional parameters */
-#define OPTIONAL_POINTER \
- optional_pointer = tvb_get_guint8(tvb, offset); \
+#define OPTIONAL_POINTER(ptr_size) \
+ if (ptr_size == POINTER_LENGTH) \
+ optional_pointer = tvb_get_guint8(tvb, offset); \
+ else \
+ optional_pointer = tvb_get_letohs(tvb, offset); \
proto_tree_add_uint(sccp_tree, hf_sccp_optional_pointer, tvb, \
- offset, POINTER_LENGTH, optional_pointer); \
+ offset, ptr_size, optional_pointer); \
optional_pointer += offset; \
- offset += POINTER_LENGTH;
+ if (ptr_size == POINTER_LENGTH_LONG) \
+ optional_pointer += 1; \
+ offset += ptr_size;
+
/* Extract the message type; all other processing is based on this */
message_type = tvb_get_guint8(tvb, MESSAGE_TYPE_OFFSET);
offset = MESSAGE_TYPE_LENGTH;
- if (check_col(pinfo->cinfo, COL_INFO)) {
- col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
val_to_str(message_type, sccp_message_type_acro_values, "Unknown"));
- };
if (sccp_tree) {
/* add the message type to the protocol tree */
PARAMETER_CLASS, offset,
PROTOCOL_CLASS_LENGTH);
- VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
- OPTIONAL_POINTER
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ OPTIONAL_POINTER(POINTER_LENGTH)
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CALLED_PARTY_ADDRESS,
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CLASS, offset,
PROTOCOL_CLASS_LENGTH);
- OPTIONAL_POINTER
+ OPTIONAL_POINTER(POINTER_LENGTH)
break;
case MESSAGE_TYPE_CREF:
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_REFUSAL_CAUSE, offset,
REFUSAL_CAUSE_LENGTH);
- OPTIONAL_POINTER
+ OPTIONAL_POINTER(POINTER_LENGTH)
break;
case MESSAGE_TYPE_RLSD:
PARAMETER_RELEASE_CAUSE, offset,
RELEASE_CAUSE_LENGTH);
- OPTIONAL_POINTER
+ OPTIONAL_POINTER(POINTER_LENGTH)
break;
case MESSAGE_TYPE_RLC:
PARAMETER_SEGMENTING_REASSEMBLING,
offset, SEGMENTING_REASSEMBLING_LENGTH);
- VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
variable_pointer1);
break;
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CLASS, offset,
PROTOCOL_CLASS_LENGTH);
- VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
- VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
- VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CALLED_PARTY_ADDRESS,
PARAMETER_RETURN_CAUSE, offset,
RETURN_CAUSE_LENGTH);
- VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
- VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
- VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CALLED_PARTY_ADDRESS,
offset,
DESTINATION_LOCAL_REFERENCE_LENGTH);
- VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
variable_pointer1);
break;
PARAMETER_HOP_COUNTER, offset,
HOP_COUNTER_LENGTH);
- VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
- VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
- VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
- OPTIONAL_POINTER
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
+ OPTIONAL_POINTER(POINTER_LENGTH)
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CALLED_PARTY_ADDRESS,
PARAMETER_HOP_COUNTER, offset,
HOP_COUNTER_LENGTH);
- VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
- VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
- VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
- OPTIONAL_POINTER
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
+ OPTIONAL_POINTER(POINTER_LENGTH)
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CALLED_PARTY_ADDRESS,
break;
case MESSAGE_TYPE_LUDT:
- if (mtp3_standard == ITU_STANDARD)
+ if (mtp3_standard != ANSI_STANDARD)
{
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CLASS, offset,
PARAMETER_HOP_COUNTER, offset,
HOP_COUNTER_LENGTH);
- VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
- VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
- VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
- OPTIONAL_POINTER
+ 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)
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CALLED_PARTY_ADDRESS,
break;
case MESSAGE_TYPE_LUDTS:
- if (mtp3_standard == ITU_STANDARD)
+ if (mtp3_standard != ANSI_STANDARD)
{
offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_RETURN_CAUSE, offset,
PARAMETER_HOP_COUNTER, offset,
HOP_COUNTER_LENGTH);
- VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
- VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
- VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
- OPTIONAL_POINTER
+ 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)
dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_CALLED_PARTY_ADDRESS,
{
proto_item *sccp_item;
proto_tree *sccp_tree = NULL;
+ const mtp3_addr_pc_t *mtp3_addr_p;
/* Make entry in the Protocol column on summary display */
if (check_col(pinfo->cinfo, COL_PROTOCOL))
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP");
+ switch(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;
+ };
/* In the interest of speed, if "tree" is NULL, don't do any work not
necessary to generate protocol tree items. */
sccp_tree = proto_item_add_subtree(sccp_item, ett_sccp);
}
+ /* Set whether message is UPLINK, DOWNLINK, or of UNKNOWN direction */
+
+ if (pinfo->net_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
+ * we can safely cast them.
+ */
+ mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->net_src.data;
+
+ if (sccp_source_pc_global == mtp3_addr_p->pc)
+ {
+ pinfo->p2p_dir = P2P_DIR_SENT;
+ }
+ else
+ {
+ /* assuming if net_src was SS7 PC then net_dst will be too */
+ mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->net_dst.data;
+
+ if (sccp_source_pc_global == mtp3_addr_p->pc)
+ {
+ pinfo->p2p_dir = P2P_DIR_RECV;
+ }
+ else
+ {
+ pinfo->p2p_dir = P2P_DIR_UNKNOWN;
+ }
+ }
+ }
+
/* dissect the message */
dissect_sccp_message(tvb, pinfo, sccp_tree, tree);
}
"", HFILL}},
{ &hf_sccp_variable_pointer1,
{ "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1",
- FT_UINT8, BASE_DEC, NULL, 0x0,
+ FT_UINT16, BASE_DEC, NULL, 0x0,
"", HFILL}},
{ &hf_sccp_variable_pointer2,
{ "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2",
- FT_UINT8, BASE_DEC, NULL, 0x0,
+ FT_UINT16, BASE_DEC, NULL, 0x0,
"", HFILL}},
{ &hf_sccp_variable_pointer3,
{ "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3",
- FT_UINT8, BASE_DEC, NULL, 0x0,
+ FT_UINT16, BASE_DEC, NULL, 0x0,
"", HFILL}},
{ &hf_sccp_optional_pointer,
{ "Pointer to Optional parameter", "sccp.optional_pointer",
- FT_UINT8, BASE_DEC, NULL, 0x0,
+ FT_UINT16, BASE_DEC, NULL, 0x0,
"", HFILL}},
{ &hf_sccp_ssn,
{ "Called or Calling SubSystem Number", "sccp.ssn",
{ "PC", "sccp.called.pc",
FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
"", HFILL}},
+ { &hf_sccp_called_ansi_pc,
+ { "PC", "sccp.called.ansi_pc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_called_chinese_pc,
+ { "PC", "sccp.called.chinese_pc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
{ &hf_sccp_called_pc_network,
{ "PC Network",
"sccp.called.network",
{ "PC", "sccp.calling.pc",
FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
"", HFILL}},
+ { &hf_sccp_calling_ansi_pc,
+ { "PC", "sccp.calling.ansi_pc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_calling_chinese_pc,
+ { "PC", "sccp.calling.chinese_pc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
{ &hf_sccp_calling_pc_network,
{ "PC Network",
"sccp.calling.network",
/* ISNI is ANSI only */
{ &hf_sccp_ansi_isni_mi,
{ "ISNI Mark for Identification Indicator", "sccp.isni.mi",
- FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_MI_MASK,
+ FT_UINT8, BASE_HEX, VALS(sccp_isni_mark_for_id_values), ANSI_ISNI_MI_MASK,
"", HFILL}},
{ &hf_sccp_ansi_isni_iri,
{ "ISNI Routing Indicator", "sccp.isni.iri",
- FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_IRI_MASK,
+ FT_UINT8, BASE_HEX, VALS(sccp_isni_iri_values), ANSI_ISNI_IRI_MASK,
"", HFILL}},
{ &hf_sccp_ansi_isni_ti,
{ "ISNI Type Indicator", "sccp.isni.ti",
- FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_TI_MASK,
+ FT_UINT8, BASE_HEX, VALS(sccp_isni_ti_values), ANSI_ISNI_TI_MASK,
"", HFILL}},
{ &hf_sccp_ansi_isni_netspec,
{ "ISNI Network Specific (Type 1)", "sccp.isni.netspec",
proto_sccp = proto_register_protocol("Signalling Connection Control Part",
"SCCP", "sccp");
+ register_dissector("sccp", dissect_sccp, proto_sccp);
+
/* Required function calls to register the header fields and subtrees used */
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);
+
+ prefs_register_uint_preference(sccp_module, "source_pc",
+ "Source PC",
+ "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, "show_length",
+ "Show length",
+ "Show parameter length in the protocol tree",
+ &sccp_show_length);
}
void
{
dissector_handle_t sccp_handle;
- sccp_handle = create_dissector_handle(dissect_sccp, proto_sccp);
+ sccp_handle = find_dissector("sccp");
dissector_add("mtp3.service_indicator", SCCP_SI, sccp_handle);
dissector_add("m3ua.protocol_data_si", SCCP_SI, sccp_handle);