/* packet-sua.c
* Routines for SS7 SCCP-User Adaptation Layer (SUA) dissection
* It is hopefully (needs testing) compilant to
- * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-sua-14.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-sua-15.txt
*
* Copyright 2002, 2003 Michael Tuexen <tuexen [AT] fh-muenster.de>
*
- * $Id: packet-sua.c,v 1.15 2003/04/19 20:09:00 tuexen Exp $
+ * $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
{ MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAUD, "Destination state audit (DAUD)" },
{ MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_SCON, "SS7 Network congestion state (SCON)" },
{ MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUPU, "Destination userpart unavailable (DUPU)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DRST, "Destination Restricted (DRST)" },
{ MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP up (UP)" },
{ MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP down (DOWN)" },
{ MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "Heartbeat (BEAT)" },
{ MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAUD, "DAUD" },
{ MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_SCON, "SCON" },
{ MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUPU, "DUPU" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DRST, "DRST" },
{ MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP_UP" },
{ MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP_DOWN" },
{ MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "BEAT" },
static int hf_drn_label_start = -1;
static int hf_drn_label_end = -1;
static int hf_drn_label_value = -1;
+static int hf_gt_reserved = -1;
+static int hf_gti = -1;
static int hf_number_of_digits = -1;
static int hf_translation_type = -1;
static int hf_numbering_plan = -1;
static gint ett_sua_return_on_error_bit_and_protocol_class = -1;
static gint ett_sua_protcol_classes = -1;
+static dissector_handle_t data_handle;
+static dissector_table_t sua_ssn_dissector_table;
+
static void
-dissect_parameters(tvbuff_t *tlv_tvb, proto_tree *tree);
+dissect_parameters(tvbuff_t *tlv_tvb, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn);
static void
dissect_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *sua_tree)
message_class = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
message_type = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
- if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (check_col(pinfo->cinfo, COL_INFO))
col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_class * 256 + message_type, message_class_type_acro_values, "reserved"));
- col_set_fence(pinfo->cinfo, COL_INFO);
- };
if (sua_tree) {
/* add the components of the common header to the protocol tree */
{ 0x14, "Destination status unknown" },
{ 0x15, "Invalid network appearance" },
{ 0x16, "Missing parameter" },
- { 0x17, "Routing key change refused" },
{ 0x19, "Invalid routing context" },
{ 0x1a, "No configured AS for ASP" },
{ 0x1b, "Subsystem status unknown" },
tvbuff_t *parameters_tvb;
parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1);
- dissect_parameters(parameters_tvb, parameter_tree);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
}
static void
tvbuff_t *parameters_tvb;
parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1);
- dissect_parameters(parameters_tvb, parameter_tree);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
}
#define REGISTRATION_STATUS_LENGTH 4
{ 8, "Error - insufficient resources" },
{ 9, "Error - unsupported RK parameter field" },
{ 10, "Error - unsupported/invalid traffic mode type" },
+ { 11, "Error - routing key change refused" },
{ 0, NULL } };
static void
#define ADDRESS_SSN_BITMASK 0x0001
static void
-dissect_source_address_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+dissect_source_address_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, guint8 *ssn)
{
proto_item *address_indicator_item;
proto_tree *address_indicator_tree;
tvbuff_t *parameters_tvb;
- proto_tree_add_item(parameter_tree, hf_source_address_routing_indicator, parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
- address_indicator_item = proto_tree_add_text(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, "Address Indicator");
- address_indicator_tree = proto_item_add_subtree(address_indicator_item, ett_sua_source_address_indicator);
- proto_tree_add_item(address_indicator_tree, hf_source_address_reserved_bits, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
- proto_tree_add_item(address_indicator_tree, hf_source_address_gt_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
- proto_tree_add_item(address_indicator_tree, hf_source_address_pc_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
- proto_tree_add_item(address_indicator_tree, hf_source_address_ssn_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ if(parameter_tree) {
+ proto_tree_add_item(parameter_tree, hf_source_address_routing_indicator, parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ address_indicator_item = proto_tree_add_text(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, "Address Indicator");
+ address_indicator_tree = proto_item_add_subtree(address_indicator_item, ett_sua_source_address_indicator);
+ proto_tree_add_item(address_indicator_tree, hf_source_address_reserved_bits, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_source_address_gt_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_source_address_pc_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_source_address_ssn_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ }
parameters_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETERS_OFFSET, -1, -1);
- dissect_parameters(parameters_tvb, parameter_tree);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, ssn, NULL);
}
static void
-dissect_destination_address_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+dissect_destination_address_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, guint8 *ssn)
{
proto_item *address_indicator_item;
proto_tree *address_indicator_tree;
tvbuff_t *parameters_tvb;
- proto_tree_add_item(parameter_tree, hf_destination_address_routing_indicator, parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
- address_indicator_item = proto_tree_add_text(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, "Address Indicator");
- address_indicator_tree = proto_item_add_subtree(address_indicator_item, ett_sua_destination_address_indicator);
- proto_tree_add_item(address_indicator_tree, hf_destination_address_reserved_bits, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
- proto_tree_add_item(address_indicator_tree, hf_destination_address_gt_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
- proto_tree_add_item(address_indicator_tree, hf_destination_address_pc_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
- proto_tree_add_item(address_indicator_tree, hf_destination_address_ssn_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ if(parameter_tree) {
+ proto_tree_add_item(parameter_tree, hf_destination_address_routing_indicator, parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ address_indicator_item = proto_tree_add_text(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, "Address Indicator");
+ address_indicator_tree = proto_item_add_subtree(address_indicator_item, ett_sua_destination_address_indicator);
+ proto_tree_add_item(address_indicator_tree, hf_destination_address_reserved_bits, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_destination_address_gt_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_destination_address_pc_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_destination_address_ssn_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ }
parameters_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETERS_OFFSET, -1, -1);
- dissect_parameters(parameters_tvb, parameter_tree);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, ssn);
}
#define SOURCE_REFERENCE_NUMBER_LENGTH 4
#define DATA_PARAMETER_DATA_OFFSET PARAMETER_VALUE_OFFSET
static void
-dissect_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+dissect_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, tvbuff_t **data_tvb)
{
guint16 data_length;
data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
- proto_tree_add_item(parameter_tree, hf_data, parameter_tvb, DATA_PARAMETER_DATA_OFFSET, data_length, NETWORK_BYTE_ORDER);
- proto_item_append_text(parameter_item, " (SS7 message of %u byte%s)", data_length, plurality(data_length, "", "s"));
+
+ if(parameter_tree) {
+ proto_tree_add_item(parameter_tree, hf_data, parameter_tvb, DATA_PARAMETER_DATA_OFFSET, data_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (SS7 message of %u byte%s)", data_length, plurality(data_length, "", "s"));
+ }
+
+ if(data_tvb)
+ {
+ *data_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, data_length, data_length);
+ }
}
tvbuff_t *parameters_tvb;
parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1);
- dissect_parameters(parameters_tvb, parameter_tree);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
}
#define DRN_START_LENGTH 1
#define DRN_END_LENGTH 1
tvbuff_t *parameters_tvb;
parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1);
- dissect_parameters(parameters_tvb, parameter_tree);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
}
#define SMI_LENGTH 1
proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CONGESTION_LEVEL_OFFSET));
}
+#define GTI_LENGTH 1
#define NO_OF_DIGITS_LENGTH 1
#define TRANSLATION_TYPE_LENGTH 1
#define NUMBERING_PLAN_LENGTH 1
#define NATURE_OF_ADDRESS_LENGTH 1
-#define NO_OF_DIGITS_OFFSET PARAMETER_VALUE_OFFSET
+#define GTI_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
+#define NO_OF_DIGITS_OFFSET (GTI_OFFSET + GTI_LENGTH)
#define TRANSLATION_TYPE_OFFSET (NO_OF_DIGITS_OFFSET + NO_OF_DIGITS_LENGTH)
#define NUMBERING_PLAN_OFFSET (TRANSLATION_TYPE_OFFSET + TRANSLATION_TYPE_LENGTH)
#define NATURE_OF_ADDRESS_OFFSET (NUMBERING_PLAN_OFFSET + NUMBERING_PLAN_LENGTH)
guint16 global_title_length;
global_title_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) -
- (PARAMETER_HEADER_LENGTH + NO_OF_DIGITS_LENGTH + TRANSLATION_TYPE_LENGTH + NUMBERING_PLAN_LENGTH + NATURE_OF_ADDRESS_LENGTH);
+ (PARAMETER_HEADER_LENGTH + RESERVED_3_LENGTH + GTI_LENGTH + NO_OF_DIGITS_LENGTH + TRANSLATION_TYPE_LENGTH + NUMBERING_PLAN_LENGTH + NATURE_OF_ADDRESS_LENGTH);
+ proto_tree_add_item(parameter_tree, hf_gt_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_gti, parameter_tvb, GTI_OFFSET, GTI_LENGTH, NETWORK_BYTE_ORDER);
proto_tree_add_item(parameter_tree, hf_number_of_digits, parameter_tvb, NO_OF_DIGITS_OFFSET, NO_OF_DIGITS_LENGTH, NETWORK_BYTE_ORDER);
proto_tree_add_item(parameter_tree, hf_translation_type, parameter_tvb, TRANSLATION_TYPE_OFFSET, TRANSLATION_TYPE_LENGTH, NETWORK_BYTE_ORDER);
proto_tree_add_item(parameter_tree, hf_numbering_plan, parameter_tvb, NUMBERING_PLAN_OFFSET, NUMBERING_PLAN_LENGTH, NETWORK_BYTE_ORDER);
#define SSN_LENGTH 1
#define SSN_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
+#define INVALID_SSN 0xff
static void
-dissect_ssn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+dissect_ssn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, guint8 *ssn)
{
- proto_tree_add_item(parameter_tree, hf_ssn_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, NETWORK_BYTE_ORDER);
- proto_tree_add_item(parameter_tree, hf_ssn_number, parameter_tvb, SSN_OFFSET, SSN_LENGTH, NETWORK_BYTE_ORDER);
+ *ssn = tvb_get_guint8(parameter_tvb, SSN_OFFSET);
- proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb, SSN_OFFSET));
+ if(parameter_tree) {
+ proto_tree_add_item(parameter_tree, hf_ssn_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_ssn_number, parameter_tvb, SSN_OFFSET, SSN_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", *ssn);
+ }
}
#define IPV4_ADDRESS_LENGTH 4
}
static void
-dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *tree)
+dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn)
{
guint16 tag, length, padding_length;
proto_item *parameter_item;
proto_tree *parameter_tree;
+ guint8 ssn = INVALID_SSN;
/* extract tag and length from the parameter */
tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
padding_length = tvb_length(parameter_tvb) - length;
- /* create proto_tree stuff */
- parameter_item = proto_tree_add_text(tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), val_to_str(tag, parameter_tag_values, "Unknown parameter"));
- parameter_tree = proto_item_add_subtree(parameter_item, ett_sua_parameter);
-
- /* add tag and length to the sua tree */
- proto_tree_add_item(parameter_tree, hf_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, NETWORK_BYTE_ORDER);
- proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ if (tree) {
+ /* create proto_tree stuff */
+ parameter_item = proto_tree_add_text(tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), val_to_str(tag, parameter_tag_values, "Unknown parameter"));
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_sua_parameter);
+ /* add tag and length to the sua tree */
+ proto_tree_add_item(parameter_tree, hf_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ } else {
+ parameter_tree = NULL;
+ parameter_item = NULL;
+ }
+/*
+** If no tree, only the data and ssn parameters in the source and destination
+** address need to be dissected. This in order to make dissection of the data
+** possible when there is no tree.
+*/
switch(tag) {
case DATA_PARAMETER_TAG:
- dissect_data_parameter(parameter_tvb, parameter_tree, parameter_item);
+ dissect_data_parameter(parameter_tvb, parameter_tree, parameter_item, data_tvb);
break;
case INFO_STRING_PARAMETER_TAG:
- dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case ROUTING_CONTEXT_PARAMETER_TAG:
- dissect_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case DIAGNOSTIC_INFO_PARAMETER_TAG:
- dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case HEARTBEAT_DATA_PARAMETER_TAG:
- dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case TRAFFIC_MODE_TYPE_PARAMETER_TAG:
- dissect_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case ERROR_CODE_PARAMETER_TAG:
- dissect_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case STATUS_PARAMETER_TAG:
- dissect_status_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_status_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case CONGESTION_LEVEL_PARAMETER_TAG:
- dissect_congestion_level_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_congestion_level_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case ASP_IDENTIFIER_PARAMETER_TAG:
- dissect_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case AFFECTED_POINT_CODE_PARAMETER_TAG:
- dissect_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case REGISTRATION_STATUS_PARAMETER_TAG:
- dissect_registration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_registration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case DEREGISTRATION_STATUS_PARAMETER_TAG:
- dissect_deregistration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_deregistration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG:
- dissect_local_routing_key_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_local_routing_key_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case SS7_HOP_COUNTER_PARAMETER_TAG:
- dissect_ss7_hop_counter_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_ss7_hop_counter_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case SOURCE_ADDRESS_PARAMETER_TAG:
- dissect_source_address_parameter(parameter_tvb, parameter_tree);
+ dissect_source_address_parameter(parameter_tvb, parameter_tree, source_ssn);
break;
case DESTINATION_ADDRESS_PARAMETER_TAG:
- dissect_destination_address_parameter(parameter_tvb, parameter_tree);
+ dissect_destination_address_parameter(parameter_tvb, parameter_tree, dest_ssn);
break;
case SOURCE_REFERENCE_NUMBER_PARAMETER_TAG:
- dissect_source_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_source_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG:
- dissect_destination_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_destination_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case SCCP_CAUSE_PARAMETER_TAG:
- dissect_sccp_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_sccp_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case SEQUENCE_NUMBER_PARAMETER_TAG:
- dissect_sequence_number_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_sequence_number_parameter(parameter_tvb, parameter_tree);
+ }
break;
case RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG:
- dissect_receive_sequence_number_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_receive_sequence_number_parameter(parameter_tvb, parameter_tree);
+ }
break;
case ASP_CAPABILITIES_PARAMETER_TAG:
- dissect_asp_capabilities_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_asp_capabilities_parameter(parameter_tvb, parameter_tree);
+ }
break;
case CREDIT_PARAMETER_TAG:
- dissect_credit_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_credit_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case USER_CAUSE_PARAMETER_TAG:
- dissect_user_cause_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_user_cause_parameter(parameter_tvb, parameter_tree);
+ }
break;
case NETWORK_APPEARANCE_PARAMETER_TAG:
- dissect_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case ROUTING_KEY_PARAMETER_TAG:
- dissect_routing_key_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_routing_key_parameter(parameter_tvb, parameter_tree);
+ }
break;
case REGISTRATION_RESULT_PARAMETER_TAG:
- dissect_registration_result_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_registration_result_parameter(parameter_tvb, parameter_tree);
+ }
break;
case DEREGISTRATION_RESULT_PARAMETER_TAG:
- dissect_deregistration_result_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_deregistration_result_parameter(parameter_tvb, parameter_tree);
+ }
break;
case ADDRESS_RANGE_PARAMETER_TAG:
- dissect_address_range_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_address_range_parameter(parameter_tvb, parameter_tree);
+ }
break;
case CORRELATION_ID_PARAMETER_TAG:
- dissect_correlation_id_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_correlation_id_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case IMPORTANCE_PARAMETER_TAG:
- dissect_importance_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_importance_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case MESSAGE_PRIORITY_PARAMETER_TAG:
- dissect_message_priority_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_message_priority_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case PROTOCOL_CLASS_PARAMETER_TAG:
- dissect_protocol_class_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_protocol_class_parameter(parameter_tvb, parameter_tree);
+ }
break;
case SEQUENCE_CONTROL_PARAMETER_TAG:
- dissect_sequence_control_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_sequence_control_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case SEGMENTATION_PARAMETER_TAG:
- dissect_segmentation_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_segmentation_parameter(parameter_tvb, parameter_tree);
+ }
break;
case SMI_PARAMETER_TAG:
- dissect_smi_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_smi_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case TID_LABEL_PARAMETER_TAG:
- dissect_tid_label_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_tid_label_parameter(parameter_tvb, parameter_tree);
+ }
break;
case DRN_LABEL_PARAMETER_TAG:
- dissect_drn_label_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_drn_label_parameter(parameter_tvb, parameter_tree);
+ }
break;
case GLOBAL_TITLE_PARAMETER_TAG:
- dissect_global_title_parameter(parameter_tvb, parameter_tree);
+ if (parameter_tree) {
+ dissect_global_title_parameter(parameter_tvb, parameter_tree);
+ }
break;
case POINT_CODE_PARAMETER_TAG:
- dissect_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case SUBSYSTEM_NUMBER_PARAMETER_TAG:
- dissect_ssn_parameter(parameter_tvb, parameter_tree, parameter_item);
+ dissect_ssn_parameter(parameter_tvb, parameter_tree, parameter_item, &ssn);
+ if(source_ssn)
+ {
+ *source_ssn = ssn;
+ }
+ if(dest_ssn)
+ {
+ *dest_ssn = ssn;
+ }
break;
case IPV4_ADDRESS_PARAMETER_TAG:
- dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case HOSTNAME_PARAMETER_TAG:
- dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
case IPV6_ADDRESS_PARAMETER_TAG:
- dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
default:
- dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ if (parameter_tree) {
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
break;
};
- if (padding_length > 0)
+ if (parameter_tree && (padding_length > 0))
proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
}
static void
-dissect_parameters(tvbuff_t *parameters_tvb, proto_tree *tree)
+dissect_parameters(tvbuff_t *parameters_tvb, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn)
{
gint offset, length, total_length, remaining_length;
tvbuff_t *parameter_tvb;
total_length = MIN(total_length, remaining_length);
/* create a tvb for the parameter including the padding bytes */
parameter_tvb = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
- dissect_parameter(parameter_tvb, tree);
+ dissect_parameter(parameter_tvb, tree, data_tvb, source_ssn, dest_ssn);
/* get rid of the handled parameter */
offset += total_length;
}
}
static void
-dissect_sua_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *sua_tree)
+dissect_sua_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *sua_tree, proto_tree *tree)
{
tvbuff_t *common_header_tvb;
tvbuff_t *parameters_tvb;
+ tvbuff_t *data_tvb = NULL;
+ guint8 source_ssn = INVALID_SSN;
+ guint8 dest_ssn = INVALID_SSN;
common_header_tvb = tvb_new_subset(message_tvb, COMMON_HEADER_OFFSET, COMMON_HEADER_LENGTH, COMMON_HEADER_LENGTH);
dissect_common_header(common_header_tvb, pinfo, sua_tree);
- if (sua_tree) {
- parameters_tvb = tvb_new_subset(message_tvb, COMMON_HEADER_LENGTH, -1, -1);
- dissect_parameters(parameters_tvb, sua_tree);
+ parameters_tvb = tvb_new_subset(message_tvb, COMMON_HEADER_LENGTH, -1, -1);
+ dissect_parameters(parameters_tvb, sua_tree, &data_tvb, &source_ssn, &dest_ssn);
+
+ /* If there was SUA data it could be dissected */
+ if(data_tvb)
+ {
+ /* Try subdissectors (if we found a valid SSN on the current message) */
+ if ((dest_ssn == INVALID_SSN ||
+ !dissector_try_port(sua_ssn_dissector_table, dest_ssn, data_tvb, pinfo, tree))
+ && (source_ssn == INVALID_SSN ||
+ !dissector_try_port(sua_ssn_dissector_table, source_ssn, data_tvb, pinfo, tree)))
+ {
+ /* No sub-dissection occured, treat it as raw data */
+ call_dissector(data_handle, data_tvb, pinfo, sua_tree);
+ }
}
}
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "SUA");
+ /* Clear entries in Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
/* In the interest of speed, if "tree" is NULL, don't do any work not
necessary to generate protocol tree items. */
if (tree) {
};
/* dissect the message */
- dissect_sua_message(message_tvb, pinfo, sua_tree);
+ dissect_sua_message(message_tvb, pinfo, sua_tree, tree);
}
/* Register the protocol with Ethereal */
{ &hf_info_string, { "Info string", "sua.info_string", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL } },
{ &hf_routing_context, { "Routing context", "sua.routing_context", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_diagnostic_information_info, { "Diagnostic Information", "sua.diagnostic_information", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
- { &hf_heartbeat_data, { "Heratbeat Data", "sua.heartbeat_data", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_heartbeat_data, { "Heartbeat Data", "sua.heartbeat_data", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
{ &hf_traffic_mode_type, { "Traffic mode Type", "sua.traffic_mode_type", FT_UINT32, BASE_DEC, VALS(traffic_mode_type_values), 0x0, "", HFILL } },
{ &hf_error_code, { "Error code", "sua.error_code", FT_UINT32, BASE_DEC, VALS(error_code_values), 0x0, "", HFILL } },
{ &hf_status_type, { "Status type", "sua.status_type", FT_UINT16, BASE_DEC, VALS(status_type_values), 0x0, "", HFILL } },
{ &hf_drn_label_start, { "Start", "sua.drn_label_start", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_drn_label_end, { "End", "sua.drn_label_end", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_drn_label_value, { "Label Value", "sua.drn_label_value", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_gt_reserved, { "Reserved", "sua.gt_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_gti, { "GTI", "sua.gti", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
{ &hf_number_of_digits, { "Number of Digits", "sua.global_title_number_of_digits", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_translation_type, { "Translation Type", "sua.global_title_translation_type", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
{ &hf_numbering_plan, { "Numbering Plan", "sua.global_title_numbering_plan", FT_UINT8, BASE_HEX, VALS(numbering_plan_values), 0x0, "", HFILL } },
{ &hf_nature_of_address, { "Nature of Address", "sua.global_title_nature_of_address", FT_UINT8, BASE_HEX, VALS(nature_of_address_values), 0x0, "", HFILL } },
- { &hf_nature_of_address, { "Nature Of Address", "sua.global_title_nature_of_address", FT_UINT8, BASE_HEX, VALS(nature_of_address_values), 0x0, "", HFILL } },
{ &hf_global_title, { "Global Title", "sua.global_title_signals", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
{ &hf_point_code_dpc, { "Point Code", "sua.point_code", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_ssn_reserved, { "Reserved", "sua.ssn_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
- { &hf_ssn_number, { "Subsystem Number", "sua.ssn_number", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_ssn_number, { "Subsystem Number", "sua.ssn", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_ipv4, { "IP Version 4 address", "sua.ipv4_address", FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL } },
{ &hf_hostname, { "Hostname", "sua.hostname.name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL } },
{ &hf_ipv6, { "IP Version 6 address", "sua.ipv6_address", FT_IPv6, BASE_NONE, NULL, 0x0, "", HFILL } },
sua_module = prefs_register_protocol(proto_sua, NULL);
prefs_register_obsolete_preference(sua_module, "sua_version");
+
+ sua_ssn_dissector_table = register_dissector_table("sua.ssn", "SUA SSN", FT_UINT8, BASE_DEC);
}
void
sua_handle = create_dissector_handle(dissect_sua, proto_sua);
dissector_add("sctp.ppi", SUA_PAYLOAD_PROTOCOL_ID, sua_handle);
dissector_add("sctp.port", SCTP_PORT_SUA, sua_handle);
+
+ data_handle = find_dissector("data");
}