* 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 "packet-e164.h"
#include "packet-e212.h"
#include "packet-frame.h"
-#include "tap.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
/* 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 */
{ PARAMETER_SEGMENTATION, "Segmentation" },
{ PARAMETER_HOP_COUNTER, "Hop Counter" },
{ PARAMETER_IMPORTANCE, "Importance (ITU)" },
- { PARAMETER_LONG_DATA, "Long Data (ITU)" },
+ { PARAMETER_LONG_DATA, "Long Data" },
{ PARAMETER_ISNI, "Intermediate Signaling Network Identification (ANSI)" },
{ 0, NULL } };
{ 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.
/* * * * * * * * * * * * * * * * * * * * * * * * * *
* Global Title: ITU GTI == 0011, ANSI GTI == 0001 *
* * * * * * * * * * * * * * * * * * * * * * * * * */
-#define GT_NP_MASK 0xf0
-#define GT_NP_SHIFT 4
-#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
/* 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
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;
static gint ett_sccp_xudt_msg_fragment = -1;
static gint ett_sccp_xudt_msg_fragments = -1;
static gint ett_sccp_assoc = -1;
-static gint ett_sccp_digits = -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 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"},
+ { 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 }
};
static emem_tree_t* assocs = NULL;
static sccp_assoc_info_t* assoc;
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};
+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){
+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++;
return a;
}
-void reset_sccp_assoc(void) {
+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) {
+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);
if(assoc)
return assoc;
- opck = opc->type == AT_SS7PC ? mtp3_pc_hash((const mtp3_addr_pc_t *)opc->data) : g_str_hash(address_to_str(opc));
- dpck = dpc->type == AT_SS7PC ? mtp3_pc_hash((const mtp3_addr_pc_t *)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) {
{
/* 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}
+ {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 = new_assoc(opck, dpck);
+ se_tree_insert32_array(assocs, bw_key, assoc);
assoc->has_bw_key = TRUE;
}
{1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
};
- if ( ( assoc = se_tree_lookup32_array(assocs,bw_key) ) ) {
+ if ( ( assoc = se_tree_lookup32_array(assocs, bw_key) ) ) {
goto got_assoc;
}
- if ( (assoc = se_tree_lookup32_array(assocs,fw_key) ) ) {
+ if ( (assoc = se_tree_lookup32_array(assocs, fw_key) ) ) {
goto 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);
+ 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);
+ se_tree_insert32_array(assocs, fw_key, assoc);
assoc->has_fw_key = TRUE;
}
emem_tree_key_t fw_key[] = {
{1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
};
- if ( ( assoc = se_tree_lookup32_array(assocs,bw_key) ) ) {
+ if ( ( assoc = se_tree_lookup32_array(assocs, bw_key) ) ) {
goto got_assoc_rlc;
}
- if ( (assoc = se_tree_lookup32_array(assocs,fw_key) ) ) {
+ if ( (assoc = se_tree_lookup32_array(assocs, fw_key) ) ) {
goto got_assoc_rlc;
}
- assoc = new_assoc(dpck,opck);
+ 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);
+ 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);
+ se_tree_insert32_array(assocs, fw_key, assoc);
assoc->has_fw_key = TRUE;
}
break;
{1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
};
- assoc = se_tree_lookup32_array(assocs,key);
+ assoc = se_tree_lookup32_array(assocs, key);
if (assoc) {
if (assoc->calling_dpc == dpck) {
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);
}
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);
}
|| m == SCCP_MSG_TYPE_XUDT|| m == SCCP_MSG_TYPE_XUDTS \
|| m == SCCP_MSG_TYPE_LUDT|| m == SCCP_MSG_TYPE_LUDTS)
-static proto_item *
-dissect_sccp_gt_address_information(tvbuff_t *tvb, proto_tree *tree,
- guint length, gboolean even_length,
- gboolean called)
+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;
- proto_item *digits_item, *hidden_item;
- char gt_digits[GT_MAX_SIGNALS+1] = { 0 };
+ 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;
g_strlcat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values,
- "Unknown"), GT_MAX_SIGNALS+1);
+ "Unknown: %d"), GT_MAX_SIGNALS+1);
/* If the last signal is NOT filler */
if (offset != (length - 1) || even_length == TRUE)
g_strlcat(gt_digits, val_to_str(even_signal, sccp_address_signal_values,
- "Unknown"), GT_MAX_SIGNALS+1);
+ "Unknown: %d"), GT_MAX_SIGNALS+1);
offset += GT_SIGNAL_LENGTH;
}
*gt_ptr = (guint8 *)ep_strdup(gt_digits);
}
- digits_item = 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);
+ 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);
- hidden_item = proto_tree_add_string(tree, hf_sccp_gt_digits, tvb, 0, length,
- gt_digits);
- PROTO_ITEM_SET_HIDDEN(hidden_item);
+ 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);
+ }
+ }
- return digits_item;
+ 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_item *digits_item = 0;
- proto_tree *gt_tree = 0;
- proto_tree *digits_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 = 0, tt, np = 0, es;
+ guint8 odd_even, nai = 0, np = 0, es;
gboolean even = TRUE;
/* Shift GTI to where we can work with it */
(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;
}
signals_tvb = tvb_new_subset(tvb, offset, (length - offset),
(length - offset));
- digits_item = dissect_sccp_gt_address_information(signals_tvb, gt_tree,
+ digits_tree = dissect_sccp_gt_address_information(signals_tvb, pinfo, gt_tree,
(length - offset),
- even, called);
+ 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) {
- digits_tree = proto_item_add_subtree(digits_item,
- ett_sccp_digits);
dissect_e164_cc(signals_tvb, digits_tree, 0, TRUE);
}
break;
case GT_NP_LAND_MOBILE:
- digits_tree = proto_item_add_subtree(digits_item,
- ett_sccp_digits);
- dissect_e212_mcc_mnc(signals_tvb, digits_tree, 0);
+ dissect_e212_mcc_mnc_in_address(signals_tvb, pinfo, digits_tree, 0);
break;
default:
break;
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,
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);
: hf_sccp_calling_national_indicator,
tvb, 0, ADDRESS_INDICATOR_LENGTH, national);
if (national == 0)
- expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_NOTE, "Address is coded to "
+ 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.");
}
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;
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
}
proto_tree_add_item(call_tree, called ? hf_sccp_called_itu_pc
: hf_sccp_calling_itu_pc,
- tvb, offset, ITU_PC_LENGTH, TRUE);
+ tvb, offset, ITU_PC_LENGTH, ENC_LITTLE_ENDIAN);
offset += ITU_PC_LENGTH;
- }else if (decode_mtp3_standard == JAPAN_STANDARD) {
+ } else if (decode_mtp3_standard == JAPAN_STANDARD) {
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);
}
proto_tree_add_item(call_tree, called ? hf_sccp_called_japan_pc
: hf_sccp_calling_japan_pc,
- tvb, offset, JAPAN_PC_LENGTH, TRUE);
+ tvb, offset, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
offset += JAPAN_PC_LENGTH;
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);
+ guint *ssn_ptr = called ? &(sccp_msg->data.ud.called_ssn) : &(sccp_msg->data.ud.calling_ssn);
*ssn_ptr = ssn;
}
/* 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 (g_ascii_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);
+ 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;
- }
+ *ssn_ptr = ssn;
+ }
- proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
+ proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
: hf_sccp_calling_ssn,
tvb, offset, ADDRESS_SSN_LENGTH, ssn);
hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset,
- ADDRESS_SSN_LENGTH, ssn);
+ 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_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) {
- 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);
+ 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");
- proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, class);
+ if (class == 0 || class == 1) {
+ guint8 handling = tvb_get_guint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK;
- if (class == 0 || class == 1)
- proto_tree_add_uint(tree, hf_sccp_handling, tvb, 0, length, handling);
+ pi = proto_tree_add_item(tree, hf_sccp_handling, tvb, 0, length, ENC_NA);
+ handling >>= CLASS_SPARE_HANDLING_SHIFT;
+
+ if (match_strval(handling, sccp_class_handling_values) == NULL) {
+ expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "Invalid message handling");
+ }
+ }
}
static void
return;
}
- proto_tree_add_item(tree, hf_sccp_more, tvb, 0, length, FALSE);
+ proto_tree_add_item(tree, hf_sccp_more, tvb, 0, length, ENC_BIG_ENDIAN);
}
static void
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, "%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, 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);
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
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);
}
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);
}
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);
}
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);
}
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);
}
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;
- }
+ 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 (handle) {
- if (uses_tcap) {
- call_tcap_dissector(handle, tvb, pinfo, tree);
- } else {
- call_dissector(handle, tvb, pinfo, tree);
- }
- return;
+ if (uses_tcap) {
+ call_tcap_dissector(handle, tvb, pinfo, tree);
+ } else {
+ call_dissector(handle, tvb, pinfo, tree);
+ }
+ return;
}
}
- 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, packet_info *pinfo, proto_tree *tree, guint length)
{
- guint8 first, class, remaining;
- guint32 slrx;
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;
-
- slrx = tvb_get_letoh24(tvb, 1);
-
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, 1, first);
- proto_tree_add_uint(param_tree, hf_sccp_segmentation_class, tvb, 0, 1, class);
- proto_tree_add_uint(param_tree, hf_sccp_segmentation_remaining, tvb, 0, 1,
- remaining);
+ 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;
return;
}
- proto_tree_add_uint(param_tree, hf_sccp_segmentation_slr, tvb, 1, length-1,
- slrx);
+ 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, 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);
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;
+ 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, TRUE);
+ ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA);
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_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:
{
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_) {
+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;
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)) {
- /* 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"));
- };
+ /* 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 */
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,
- "Segmented Data");
- dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
- PARAMETER_DATA, variable_pointer1);
+ proto_tree_add_text(sccp_tree, tvb, variable_pointer1,
+ tvb_get_guint8(tvb, variable_pointer1)+1,
+ "Segmented Data");
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DATA, variable_pointer1);
} else {
- 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 */
+ 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? */
-
- new_tvb = process_reassembled_data(tvb, variable_pointer1 + 1, pinfo,
- "Reassembled Message", 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) ");
- } 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) ");
- }
+ more); /* More fragments? */
+
+ new_tvb = process_reassembled_data(tvb, variable_pointer1 + 1, pinfo,
+ "Reassembled SCCP", frag_msg,
+ &sccp_xudt_msg_frag_items, NULL,
+ tree);
+
+ if (frag_msg && frag_msg->next) { /* Reassembled */
+ col_append_str(pinfo->cinfo, COL_INFO, "(Message reassembled) ");
+ } else if (more) { /* Not last packet of reassembled message */
+ col_append_str(pinfo->cinfo, COL_INFO, "(Message fragment) ");
+ }
- pinfo->fragmented = save_fragmented;
+ pinfo->fragmented = save_fragmented;
- if (new_tvb)
- dissect_sccp_data_param(new_tvb, pinfo, tree);
+ if (new_tvb)
+ dissect_sccp_data_param(new_tvb, pinfo, tree);
}
/* End reassemble */
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,
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,
PARAMETER_CALLING_PARTY_ADDRESS,
variable_pointer2);
- 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 Message",
+ 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 */
- if (check_col(pinfo->cinfo, COL_INFO))
- 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) ");
- }
+ 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;
+ pinfo->fragmented = save_fragmented;
- if (new_tvb)
- dissect_sccp_data_param(new_tvb, pinfo, tree);
- }
+ if (new_tvb)
+ dissect_sccp_data_param(new_tvb, pinfo, tree);
+ }
} else {
- dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
PARAMETER_DATA, variable_pointer3);
}
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,
PARAMETER_CALLING_PARTY_ADDRESS,
variable_pointer2);
- if (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");
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;
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:
- pinfo->sccp_info = sccp_msg = new_ud_msg(pinfo,message_type);
- 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:
- pinfo->sccp_info = sccp_msg = new_ud_msg(pinfo,message_type);
- 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->data.co.next) {
- pi = proto_tree_add_uint( pt,hf_sccp_assoc_msg,tvb,0,0,m->framenum);
+ 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->data.co.label)
proto_item_append_text(pi," %s", m->data.co.label);
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;
}
}
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}
+ {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_) {
+static void
+sccp_users_update_cb(void* r, const char** err _U_)
+{
sccp_user_t* u = r;
struct _sccp_ul* c;
u->handlep = &data_handle;
}
-static void* sccp_users_copy_cb(void* n, const void* o, unsigned siz _U_) {
+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;
return n;
}
-static void sccp_users_free_cb(void*r) {
+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_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) {
+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);
{ "Pointer to Optional parameter", "sccp.optional_pointer",
FT_UINT16, BASE_DEC, NULL, 0x0,
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,
FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
NULL, HFILL }},
{ &hf_sccp_called_gt_digits,
- { "GT Digits",
+ { "Called Party Digits",
"sccp.called.digits",
FT_STRING, BASE_NONE, NULL, 0x0,
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,
FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
NULL, HFILL }},
{ &hf_sccp_calling_gt_digits,
- { "GT Digits",
+ { "Calling Party Digits",
"sccp.calling.digits",
FT_STRING, BASE_NONE, NULL, 0x0,
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,
{ "ISNI Counter", "sccp.isni.counter",
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 }
{"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, 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_xudt_msg_fragment,
&ett_sccp_xudt_msg_fragments,
- &ett_sccp_assoc,
- &ett_sccp_digits
+ &ett_sccp_assoc
};
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",65535,"DPCs for which this protocol is to be used"),
- UAT_FLD_RANGE(sccp_users,called_ssn,"Called SSNs",65535,"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_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,
- users_flds );
+ 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",
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 (in hex)",
"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);
assocs = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "sccp_associations");
{
dissector_handle_t sccp_handle;
- sccp_handle = find_dissector("sccp");
+ static gboolean initialised=FALSE;
- dissector_add("wtap_encap", WTAP_ENCAP_SCCP, sccp_handle);
- 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");
- 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");
-}
+ 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);
+}