static void dissect_error_cause(tvbuff_t *cause_tvb, proto_tree *parameter_tree) { guint16 code, length, padding_length; proto_item *cause_item; proto_tree *cause_tree; tvbuff_t *parameter_tvb, *message_tvb; code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET); length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET); padding_length = tvb_length(cause_tvb) - length; cause_item = proto_tree_add_text(parameter_tree, cause_tvb, CAUSE_HEADER_OFFSET, tvb_length(cause_tvb), "%s", val_to_str_const(code, cause_code_values, "Unknown error cause")); cause_tree = proto_item_add_subtree(cause_item, ett_asap_cause); proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH, ENC_BIG_ENDIAN); proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, ENC_BIG_ENDIAN); switch(code) { case UNRECOGNIZED_PARAMETER_CAUSE_CODE: parameter_tvb = tvb_new_subset_remaining(cause_tvb, CAUSE_INFO_OFFSET); dissect_parameter(parameter_tvb, cause_tree); break; case UNRECONGNIZED_MESSAGE_CAUSE_CODE: message_tvb = tvb_new_subset_remaining(cause_tvb, CAUSE_INFO_OFFSET); dissect_asap(message_tvb, NULL, cause_tree); break; case INVALID_VALUES: parameter_tvb = tvb_new_subset_remaining(cause_tvb, CAUSE_INFO_OFFSET); dissect_parameter(parameter_tvb, cause_tree); break; case NON_UNIQUE_PE_IDENTIFIER: break; case POOLING_POLICY_INCONSISTENT_CAUSE_CODE: parameter_tvb = tvb_new_subset_remaining(cause_tvb, CAUSE_INFO_OFFSET); dissect_parameter(parameter_tvb, cause_tree); break; case LACK_OF_RESOURCES_CAUSE_CODE: break; case INCONSISTENT_TRANSPORT_TYPE_CAUSE_CODE: parameter_tvb = tvb_new_subset_remaining(cause_tvb, CAUSE_INFO_OFFSET); dissect_parameter(parameter_tvb, cause_tree); break; case INCONSISTENT_DATA_CONTROL_CONFIGURATION_CAUSE_CODE: break; case UNKNOWN_POOL_HANDLE: break; case REJECTION_DUE_TO_SECURITY_CAUSE_CODE: break; default: dissect_unknown_cause(cause_tvb, cause_tree, cause_item); break; } if (padding_length > 0) proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, ENC_NA); }
static void dissect_parameters(tvbuff_t *parameters_tvb, proto_tree *tree) { gint offset, length, total_length, remaining_length; tvbuff_t *parameter_tvb; offset = 0; while((remaining_length = tvb_reported_length_remaining(parameters_tvb, offset)) > 0) { length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET); total_length = ADD_PADDING(length); if (remaining_length >= length) total_length = MIN(total_length, remaining_length); /* create a tvb for the parameter including the padding bytes */ parameter_tvb = tvb_new_subset_length(parameters_tvb, offset, total_length); dissect_parameter(parameter_tvb, tree); /* get rid of the handled parameter */ offset += total_length; } }
/* * Returns TRUE if there's a User Information field in this SPDU, FALSE * otherwise. */ static gboolean dissect_parameters(tvbuff_t *tvb, int offset, guint16 len, proto_tree *tree, proto_tree *ses_tree, packet_info *pinfo, guint8 *enclosure_item_flags, struct SESSION_DATA_STRUCTURE *session) { gboolean has_user_information = TRUE; proto_item *ti; proto_tree *param_tree; guint8 param_type; const char *param_str; int len_len; guint16 param_len; while (len != 0) { param_type = tvb_get_guint8(tvb, offset); param_tree = proto_tree_add_subtree(ses_tree, tvb, offset, -1, ett_ses_param, &ti, val_to_str(param_type, param_vals, "Unknown parameter type (0x%02x)")); param_str = val_to_str_const(param_type, param_vals, "Unknown"); proto_tree_add_text(param_tree, tvb, offset, 1, "Parameter type: %s", param_str); offset++; len--; param_len = get_item_len(tvb, offset, &len_len); if (len_len > len) { proto_item_set_len(ti, len + 1 ); proto_tree_add_text(param_tree, tvb, offset, len, "Parameter length doesn't fit in parameter"); return has_user_information; } len -= len_len; if (param_len > len) { proto_item_set_len(ti, len + 1 + len_len); proto_tree_add_text(param_tree, tvb, offset, len, "Parameter length: %u, should be <= %u", param_len, len); return has_user_information; } proto_item_set_len(ti, 1 + len_len + param_len); proto_tree_add_text(param_tree, tvb, offset, len_len, "Parameter length: %u", param_len); offset += len_len; if (param_str != NULL) { switch(param_type) { case Extended_User_Data: call_pres_dissector(tvb, offset, param_len, pinfo, tree, param_tree, session); break; case User_Data: call_pres_dissector(tvb, offset, param_len, pinfo, tree, param_tree, session); break; /* handle PGI's */ case Connect_Accept_Item: case Connection_Identifier: case Linking_Information: /* Yes. */ if (!dissect_parameter_group(tvb, offset, tree, param_tree, pinfo, param_len, enclosure_item_flags, session)) has_user_information = FALSE; break; /* everything else is a PI */ default: if (!dissect_parameter(tvb, offset, tree, param_tree, pinfo, param_type, param_len, enclosure_item_flags, session)) has_user_information = FALSE; break; } } offset += param_len; len -= param_len; } return has_user_information; }
static gboolean dissect_parameter_group(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pg_tree, packet_info *pinfo, guint16 pg_len, guint8 *enclosure_item_flags, struct SESSION_DATA_STRUCTURE *session) { gboolean has_user_information = TRUE; proto_item *ti; proto_tree *param_tree; guint8 param_type; const char *param_str; int len_len; guint16 param_len; while(pg_len != 0) { param_type = tvb_get_guint8(tvb, offset); ti = proto_tree_add_text(pg_tree, tvb, offset, -1, "%s", val_to_str(param_type, param_vals, "Unknown parameter type (0x%02x)")); param_tree = proto_item_add_subtree(ti, ett_ses_param); param_str = val_to_str_const(param_type, param_vals, "Unknown"); proto_tree_add_text(param_tree, tvb, offset, 1, "Parameter type: %s", param_str); offset++; pg_len--; param_len = get_item_len(tvb, offset, &len_len); if (len_len > pg_len) { proto_item_set_len(ti, pg_len + 1); proto_tree_add_text(param_tree, tvb, offset, pg_len, "Parameter length doesn't fit in parameter"); return has_user_information; } pg_len -= len_len; if (param_len > pg_len) { proto_item_set_len(ti, pg_len + 1 + len_len); proto_tree_add_text(param_tree, tvb, offset, pg_len, "Parameter length: %u, should be <= %u", param_len, pg_len); return has_user_information; } proto_item_set_len(ti, 1 + len_len + param_len); proto_tree_add_text(param_tree, tvb, offset, len_len, "Parameter length: %u", param_len); offset += len_len; if (param_str != NULL) { switch(param_type) { /* PG's in PG's are invalid, presumably */ case Extended_User_Data: case User_Data: case Connect_Accept_Item: case Connection_Identifier: case Linking_Information: proto_tree_add_text(param_tree, tvb, offset, param_len, "Parameter group inside parameter group"); break; default: if (!dissect_parameter(tvb, offset, tree, param_tree, pinfo, param_type, param_len, enclosure_item_flags, session)) has_user_information = FALSE; break; } } offset += param_len; pg_len -= param_len; } return has_user_information; }