aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-acse.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-acse.c')
-rw-r--r--epan/dissectors/packet-acse.c1767
1 files changed, 1767 insertions, 0 deletions
diff --git a/epan/dissectors/packet-acse.c b/epan/dissectors/packet-acse.c
new file mode 100644
index 0000000000..f7a4ed7e2e
--- /dev/null
+++ b/epan/dissectors/packet-acse.c
@@ -0,0 +1,1767 @@
+/* packet-acse.c
+*
+* Routine to dissect OSI ACSE Protocol packets
+*
+* $Id$
+*
+* Yuriy Sidelnikov <YSidelnikov@hotmail.com>
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998 Gerald Combs
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-acse.h"
+#include "packet-frame.h"
+#include "prefs.h"
+
+#include <epan/strutil.h>
+
+#include "asn1.h"
+#include "format-oid.h"
+
+#include "packet-ses.h"
+extern const value_string ses_vals[];
+
+/* acse header fields */
+static int proto_acse = -1;
+/* type of session envelop */
+static struct SESSION_DATA_STRUCTURE* session = NULL;
+/* acse fields defining a sub tree */
+static gint ett_acse = -1;
+static gint ett_acse_param = -1;
+static gint ett_acse_rc = -1;
+static gint ett_acse_ms = -1;
+static gint ett_acse_itm = -1;
+
+/*
+----------------------------------------------------------------------------------------------------------*/
+/* Subdissector tables */
+static dissector_table_t application_dissector_table;
+static dissector_handle_t app_handle = NULL;
+static int hf_acse_type = -1;
+static int hf_cp_type_message_length = -1;
+static int hf_protocol_version = -1;
+
+
+
+static const value_string acse_vals[] =
+{
+ {ACSE_AARQ, "A-associate request" },
+ {ACSE_AARE, "A-associate response" },
+ {ACSE_RLRQ, "A-reliase request" },
+ {ACSE_RLRE, "A-reliase response" },
+ {ACSE_ABRT, "A-abort" },
+ {0, NULL }
+};
+
+static const value_string cr_vals[] =
+{
+ {MODE_SELECTOR, "Mode Selector"},
+ {SEQUENCE_TOP, "Sequence"},
+ {SET_TOP, "Set"},
+ {0, NULL}
+};
+
+static const value_string request_sequence_top_vals[] =
+{
+ {PROTOCOL_VERSION, "Protocol version"},
+ {APPLICATION_CONTEXT_NAME, "Application context name"},
+ {CALLED_AP_TITLE, "Called AP title"},
+ {CALLED_AE_QUALIFIER, "Called AE qualifier"},
+ {CALLED_AP_INVOKATION_ID, "Called AP invokation id"},
+ {CALLED_AE_INVOKATION_ID, "Called AE invokation id"},
+ {CALLING_AP_TITLE, "Calling AP title"},
+ {CALLING_AE_QUALIFIER, "Calling AE qualifier"},
+ {CALLING_AP_INVOKATION_ID, "Calling AP invokation id"},
+ {CALLING_AE_INVOKATION_ID, "Calling AE invokation id"},
+ {IMPLEMENTATION_INFORMATION,"Implementation information"},
+ {USER_INFORMATION,"User information"},
+ {0, NULL}
+};
+static const value_string response_sequence_top_vals[] =
+{
+ {PROTOCOL_VERSION, "Protocol version"},
+ {APPLICATION_CONTEXT_NAME, "Application context name"},
+ {ACSE_RESULT, "Result"},
+ {ACSE_RESULT_SOURCE_DIAGNOSTIC, "Result source diagnostic"},
+ {RESPONDING_AP_TITLE, "Responding AP title"},
+ {RESPONDING_AE_QUALIFIER, "Responding AE qualifier"},
+ {RESPONDING_AP_INVOKATION_ID, "Responding AP invokation id"},
+ {RESPONDING_AE_INVOKATION_ID, "Responding AE invokation id"},
+ {IMPLEMENTATION_INFORMATION,"Implementation information"},
+ {USER_INFORMATION,"User information"},
+ {0, NULL}
+};
+static const value_string associate_result_values_vals[] =
+{
+ {PRESENTATION_RESULT_ACCEPTANCE,"Accepted"},
+ {PRESENTATION_RESULT_USER_REJECTION,"Rejected permanent"},
+ {PRESENTATION_RESULT_PROVIDER_REJECTION,"Rejected transient"},
+ {0, NULL}
+};
+
+static const value_string acse_associate_source_diagnostic_vals[] =
+{
+ {ACSE_SERVICE_USER,"Acse service user"},
+ {ACSE_SERVICE_PROVIDER,"Acse service provider"},
+ {0, NULL}
+};
+static const value_string acse_service_user_values_vals[] =
+{
+ {ACSE_NULL,"null"},
+ {ACSE_NO_REASON_GIVEN,"No reason given"},
+ {ACSE_APPLICATION_CONTEXT_NAME_NOT_SUPPORTED,"Application context name not supported"},
+ {ACSE_CALLING_AP_TITLE_NOT_RECOGNIZED,"Calling AP title not recognized"},
+ {ACSE_CALLING_AP_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Calling AP invokation identifier not recognized"},
+ {ACSE_CALLING_AE_QUALIFIER_NOT_RECOGNIZED,"Calling AE qualifier not recognized"},
+ {ACSE_CALLING_AE_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Calling AE invokation identifier not recognized"},
+ {ACSE_CALLED_AP_TITLE_NOT_RECOGNIZED,"Called AP title not recognized"},
+ {ACSE_CALLED_AP_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Called AP invokation identifier not recognized"},
+ {ACSE_CALLED_AE_QUALIFIER_NOT_RECOGNIZED,"Called AE qualifier not recognized"},
+ {ACSE_CALLED_AE_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Called AE invokation identifier not recognized"},
+ {0, NULL}
+};
+static const value_string acse_service_provider_values_vals[] =
+{
+ {ACSE_NULL,"Null"},
+ {ACSE_NO_REASON_GIVEN,"No reason given"},
+ {ACSE_NO_COMMON_ACSE_VERSION,"no_common_acse_version"},
+ {0, NULL}
+};
+
+static const value_string acse_user_information_vals[] =
+{
+ {ACSE_EXTERNAL_USER,"External"},
+ {0, NULL}
+};
+static const value_string sequence_list_vals[] =
+{
+ {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
+ {ABSTRACT_SYNTAX_NAME,"Abstract syntax name"},
+ {TRANSFER_SYNTAX_NAMES,"Transfer syntax names"},
+ {0, NULL}
+};
+static const value_string presentation_context_definition_vals[] =
+{
+ {SEQUENCE, "Sequence"},
+ {0, NULL}
+};
+static const value_string user_data_values_vals[] =
+{
+ {SIMPLY_ENCODED_DATA,"Simply encoded data"},
+ {FULLY_ENCODED_DATA,"Fully encoded data "},
+ {0, NULL}
+};
+static const value_string presentation_data_values[] =
+{
+ {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
+ {SINGLE_ASN1_TYPE,"Single ASN.1 type"},
+ {OCTET_ALIGNED,"Octet aligned"},
+ {ARBITRARY,"Arbitrary"},
+ {ABSTRACT_SYNTAX_NAME,"Abstract syntax name"},
+ {0, NULL}
+};
+static const value_string release_request_reason[] =
+{
+ {RRR_NORMAL,"Normal"},
+ {RRR_URGENT,"Urgent"},
+ {RRR_USER_DEFINED,"User defined"},
+ {0, NULL}
+};
+static const value_string release_response_reason[] =
+{
+ {RRPR_NORMAL,"Normal"},
+ {RRPR_URGENT,"Not finished"},
+ {RRPR_USER_DEFINED,"User defined"},
+ {0, NULL}
+};
+
+static const value_string abort_reason[] =
+{
+ {ABRT_ACSE_SERVICE_USER,"Acse service user"},
+ {ABRT_ACSE_SERVICE_PROVIDER,"Acse service provider"},
+ {0, NULL}
+};
+
+static const value_string type_app[] =
+{
+ {0,""}, /* for unknown dissector */
+ {FTAM_APP,"FTAM"},
+ {CMIP_APP,"CMIP"},
+ {0, NULL}
+};
+
+/* pointers for acse dissector */
+static proto_tree *global_tree = NULL;
+static packet_info *global_pinfo = NULL;
+/* dissector for data */
+static dissector_handle_t data_handle;
+static void
+call_app_dissector(tvbuff_t *tvb, gint offset, gint param_len,
+ packet_info *pinfo, proto_tree *tree, proto_tree *param_tree)
+{
+ /* do we have OSI app packet dissector ? */
+ if(!app_handle )
+ {
+
+ /* No - display as data */
+ if (tree)
+ {
+ proto_tree_add_text(param_tree, tvb, offset, param_len,
+ "dissector is not available");
+ }
+ }
+ else
+ {
+ /* Yes - call application dissector */
+ tvbuff_t *next_tvb;
+
+ next_tvb = tvb_new_subset(tvb, offset, param_len,
+ param_len);
+ TRY
+ {
+ call_dissector(app_handle, next_tvb, pinfo,
+ tree);
+ }
+ CATCH_ALL
+ {
+ show_exception(tvb, pinfo, tree, EXCEPT_CODE);
+ }
+ ENDTRY;
+ }
+}
+static char*
+string_to_hex(const unsigned char * in,char * out,int len)
+{
+ char ascii[MAXSTRING];
+ int i;
+ memset(&ascii,0x00,sizeof(ascii));
+for(i=0;i<len;i++)
+ {
+ unsigned char o_out = *(in+i);
+ sprintf(out+(i<<1),"%.2x",* (in+i));
+ if( ( (o_out) >= 'a') & ( (o_out) <='z') ||
+ ( (o_out) >= 'A') & ( (o_out) <='Z') ||
+ ( (o_out) >= '0') & ( (o_out) <='9')
+ )
+ {
+ ascii[i] = o_out;
+ }
+ else
+ {
+ ascii[i] = '.';
+ }
+
+ }
+ strcat(out," ");
+ strcat(out,ascii);
+ return out;
+}
+
+static int read_length(ASN1_SCK *a, proto_tree *tree, int hf_id, guint *len)
+{
+ guint length = 0;
+ gboolean def = FALSE;
+ int start = a->offset;
+ int ret;
+
+ ret = asn1_length_decode(a, &def, &length);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse length: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ if (len)
+ *len = length;
+
+ if (tree && hf_id)
+ proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start,
+length);
+
+ return ASN1_ERR_NOERROR;
+}
+static int read_integer_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, guint *i, int start, guint length)
+{
+ guint integer = 0;
+ proto_item *temp_item = NULL;
+ int ret;
+
+ ret = asn1_uint32_value_decode(a, length, &integer);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse value: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ if (i)
+ *i = integer;
+
+ if (tree && hf_id)
+ temp_item = proto_tree_add_uint(tree, hf_id, a->tvb, start,
+a->offset-start, integer);
+
+ if (new_item)
+ *new_item = temp_item;
+
+ return ASN1_ERR_NOERROR;
+}
+
+static int read_integer(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, guint *i)
+{
+ guint cls, con, tag;
+ gboolean def;
+ guint length;
+ int start = a->offset;
+ int ret;
+
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ (hf_id != -1) ? proto_registrar_get_name(hf_id) : "LDAP message",
+ asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ return read_integer_value(a, tree, hf_id, new_item, i, start, length);
+}
+/* display asn.1 Integer type */
+static void
+show_integer(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,guint item_len)
+{
+ proto_tree *acse_tree_itm = NULL;
+ proto_item *itm;
+ int ret;
+ int save_len = item_len;
+ int off = *offset;
+ itm = proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Integer");
+ acse_tree_itm = proto_item_add_subtree(itm, ett_acse_itm);
+ ret = read_integer(asn,acse_tree_itm,0,NULL,&item_len);
+ if (ret == ASN1_ERR_NOERROR )
+ {
+ *offset = asn->offset;
+ itm = proto_tree_add_text(acse_tree_itm, tvb, (*offset)-item_len,
+ item_len,
+ "Integer value: %u",item_len);
+ }
+ else
+ {
+ /* can't dissect item. Skip it. */
+ *offset = off+ save_len;
+ }
+
+}
+static void
+show_protocol_version(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *acse_tree_itm = NULL;
+ proto_item *itm;
+ guint16 flags;
+ gint length;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ (asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+
+ itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset -*offset)+
+ item_len,
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ acse_tree_itm = proto_item_add_subtree(itm, ett_acse_itm);
+ *offset = asn->offset;
+ flags = tvb_get_ntohs(tvb, *offset);
+ proto_tree_add_boolean(acse_tree_itm,hf_protocol_version, tvb, *offset,
+ 2, flags);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+static void
+print_oid_value(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ guint ret;
+ subid_t *oid;
+ guint len;
+ gchar *display_string;
+ guint length;
+ guint start=*offset;
+
+ ret = asn1_oid_value_decode (asn, item_len, &oid, &len);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ return ;
+ }
+ length = asn->offset - start;
+ display_string = format_oid(oid, len);
+ proto_tree_add_text(acse_tree, tvb, *offset,length,"Value:%s",
+ display_string);
+ g_free(display_string);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+static void
+print_oid(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int *offset,int
+item_len,gchar* d_s)
+{
+ guint ret;
+ subid_t *oid;
+ guint len;
+ guint nbytes;
+ gchar *display_string;
+ guint length;
+ guint start=*offset;
+
+ ret = asn1_oid_decode ( asn, &oid, &len, &nbytes);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ return ;
+ }
+ length = asn->offset - start;
+ display_string = format_oid(oid, len);
+ proto_tree_add_text(acse_tree, tvb, *offset,length,"Value:%s",
+ display_string);
+ if(d_s)
+ {
+ /* copy OID */
+ strcpy(d_s,display_string);
+ }
+ g_free(display_string);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+
+static void
+print_value(proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ char tmp[MAXSTRING];
+ string_to_hex(tvb_get_ptr(tvb,*offset,item_len),tmp,item_len);
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len, tmp);
+}
+static int
+get_integer_value(ASN1_SCK *asn,int length,int *offset)
+{
+ int off = *offset;
+ int asn_off = asn->offset;
+ int item_len = -1;
+ int ret;
+ /* align pointers */
+ *offset=asn->offset;
+ ret = asn1_uint32_value_decode(asn, length, &item_len);
+ /* return to present position */
+ *offset = off;
+ asn->offset = asn_off;
+
+ if (ret != ASN1_ERR_NOERROR )
+ {
+ return -1;
+ }
+ else
+ {
+ return item_len;
+ }
+
+}
+static void
+show_fully_encoded_seq(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ proto_tree *acse_tree_ms = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ guint new_item_len;
+ guint start = *offset;
+ guint header_len;
+ guint acse = 0; /* no acse id */
+ int old_offset;
+ /* print seq */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ old_offset = *offset ;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, presentation_data_values,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+
+
+ switch(type)
+ {
+ case PRESENTATION_CONTEXT_IDENTIFIER:
+ {
+ acse = get_integer_value(asn,new_item_len,offset);
+ print_value(acse_tree_ms,tvb,offset,new_item_len);
+ }
+ break;
+ case ABSTRACT_SYNTAX_NAME:
+ print_oid_value(asn,acse_tree_ms,tvb,offset,new_item_len);
+ break;
+
+ case OCTET_ALIGNED:
+ break;
+ case SINGLE_ASN1_TYPE:
+ {
+ proto_item *acse_ms;
+ /* yes, we have to call ACSE dissector */
+ acse_ms = proto_tree_add_text(acse_tree_ms, tvb, *offset,
+ new_item_len+(asn->offset-*offset),
+ "user data");
+ /* call acse dissector */
+ call_app_dissector(tvb,*offset,new_item_len,global_pinfo,global_tree,acse_tree_ms);
+ }
+ break;
+ case ARBITRARY:
+ print_value(acse_tree_ms,tvb,offset,new_item_len);
+ break;
+ default:
+ proto_tree_add_text(acse_tree, tvb, *offset,
+ new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ }
+ *offset = old_offset+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ }
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+
+}
+
+static void
+show_acse_user_information(ASN1_SCK *asn,proto_tree
+*acse_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ proto_tree *acse_tree_ms = NULL;
+ proto_tree *acse_tree_ab = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ proto_item *ab;
+ guint new_item_len;
+ guint code_item_len;
+ guint start = *offset;
+ guint header_len;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type,response_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* do we have user or provider abort ? */
+ ab = proto_tree_add_text(acse_tree_ms, tvb, *offset,
+ new_item_len+(asn->offset-*offset),
+ val_to_str(type,acse_user_information_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ab = proto_item_add_subtree(ab, ett_acse_ms);
+
+ if(type!= ACSE_EXTERNAL)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* skip type of item*/
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree_ab, 0, &code_item_len) !=
+ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ code_item_len )
+ {
+ proto_tree_add_text(acse_tree_ab, tvb, *offset, code_item_len,
+ "Wrong item.Need %u bytes but have %u", code_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset = asn->offset;
+
+ show_fully_encoded_seq(asn,acse_tree_ab,tvb,offset,code_item_len);
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+
+static void
+show_acse_result_source_diagnostic(ASN1_SCK *asn,proto_tree
+*acse_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ proto_tree *acse_tree_ms = NULL;
+ proto_tree *acse_tree_ab = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ proto_item *ab;
+ guint new_item_len;
+ guint code_item_len;
+ guint start = *offset;
+ guint header_len;
+ proto_tree *acse_tree_pr = NULL;
+ proto_item *pr;
+ int value;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type,response_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* do we have user or provider abort ? */
+ ab = proto_tree_add_text(acse_tree_ms, tvb, *offset,
+ new_item_len+(asn->offset-*offset),
+ val_to_str(type,acse_associate_source_diagnostic_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ab = proto_item_add_subtree(ab, ett_acse_ms);
+
+ /* skip type of abort*/
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &code_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset = asn->offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ code_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, code_item_len,
+ "Wrong item.Need %u bytes but have %u", code_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* skip type of constant*/
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree_ab, 0, &code_item_len) !=
+ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ code_item_len )
+ {
+ proto_tree_add_text(acse_tree_ab, tvb, *offset, code_item_len,
+ "Wrong item.Need %u bytes but have %u", code_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset = asn->offset;
+ value = get_integer_value(asn,code_item_len,offset);
+ if(type == ACSE_SERVICE_USER )
+ {
+ pr = proto_tree_add_text(acse_tree_ab, tvb, *offset,
+ code_item_len+(asn->offset-*offset),
+ val_to_str(value , acse_service_user_values_vals,
+ "Unknown item (0x%02x)"));
+ }
+ else
+ {
+ pr = proto_tree_add_text(acse_tree_ab, tvb, *offset,
+ code_item_len+(asn->offset-*offset),
+ val_to_str(value , acse_service_provider_values_vals,
+ "Unknown item (0x%02x)"));
+ }
+
+ acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
+ print_value(acse_tree_pr,tvb,offset,code_item_len);
+
+ *offset = start+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+
+}
+static void
+show_acse_result(ASN1_SCK *asn,proto_tree
+*acse_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ proto_tree *acse_tree_ms = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ guint new_item_len;
+ guint code_item_len;
+ guint start = *offset;
+ guint header_len;
+ proto_tree *acse_tree_pr = NULL;
+ proto_item *pr;
+ int value;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type,response_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &code_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ code_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, code_item_len,
+ "Wrong item.Need %u bytes but have %u", code_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset = asn->offset;
+ value = get_integer_value(asn,code_item_len,offset);
+ pr = proto_tree_add_text(acse_tree_ms, tvb, *offset,
+ code_item_len+(asn->offset-*offset),
+ val_to_str(value , associate_result_values_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
+ print_value(acse_tree_pr,tvb,offset,code_item_len);
+
+ *offset = start+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+
+static void
+show_oid(ASN1_SCK *asn,proto_tree
+*acse_tree,tvbuff_t *tvb,int *offset,int item_len,const value_string*
+v_s,gchar* oid)
+{
+ proto_tree *acse_tree_ms = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ guint new_item_len;
+ guint start = *offset;
+ guint header_len;
+ int old_offset;
+ old_offset = *offset ;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, v_s,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+ print_oid(asn,acse_tree_ms,tvb,offset,new_item_len,oid);
+ *offset = old_offset+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+static void
+show_fully_encoded_data(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ proto_tree *acse_tree_ms = NULL;
+ proto_tree *acse_tree_pc = NULL;
+ guint length;
+ guint type;
+ guint header_len;
+ proto_item *ms;
+ guint new_item_len;
+ guint start = asn->offset;
+ guint item_length = item_len;
+ acse_tree_pc = acse_tree;
+
+/* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < (guint)item_len )
+ {
+ proto_tree_add_text(acse_tree_pc, tvb, *offset, item_len,
+ "Wrong item.Need %u bytes but have %u", item_len,length);
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset =asn->offset;
+ start = *offset;
+ /* read the rest */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ int old_offset = *offset;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
+ ASN1_ERR_NOERROR)
+ {
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree_pc, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ ms = proto_tree_add_text(acse_tree_pc, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, presentation_context_definition_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+
+
+ switch(type)
+ {
+
+ case SEQUENCE:
+ show_fully_encoded_seq(asn,acse_tree_ms,tvb,offset,new_item_len);
+ *offset = old_offset+(new_item_len+header_len);
+ break;
+
+ default:
+ proto_tree_add_text(acse_tree_ms, tvb, *offset,
+ new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ *offset = old_offset+(new_item_len+header_len);
+ }
+ item_len = item_len - (new_item_len+header_len);
+
+ }
+
+
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+}
+static void
+show_abort_reason(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ gint length;
+ gint value;
+ proto_tree *acse_tree_pc = NULL;
+ proto_item *itu;
+ guint new_item_len;
+ guint start = *offset;
+ int save_len = item_len;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ *offset = asn->offset;
+ return;
+ }
+
+ if(item_len <= 0)
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Reason not specified");
+ *offset = asn->offset;
+ return;
+ }
+ itu = proto_tree_add_text(acse_tree, tvb, *offset,ABORT_REASON_LEN,
+ "Reason");
+ acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
+ (*offset)++; /* skip type */
+ asn->offset = *offset;
+ item_len--;
+ /* get length */
+ if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
+ ASN1_ERR_NOERROR)
+ {
+ *offset = asn->offset;
+ return;
+ }
+ /* try to get reason */
+ value = get_integer_value(asn,new_item_len,offset);
+
+ proto_tree_add_text(acse_tree_pc, tvb, *offset+1,new_item_len,
+ val_to_str(value,abort_reason,"Unknown item (0x%02x)"));
+ item_len-=(asn->offset-*offset)+new_item_len;
+ *offset = asn->offset+new_item_len;
+ asn->offset = *offset;
+ /* do we have User information field ? */
+ if(item_len > 0)
+ {
+ show_acse_user_information(asn,acse_tree,tvb,offset,item_len);
+ }
+ /* align the pointer */
+ (*offset)=start+save_len;
+ asn->offset = (*offset);
+}
+
+static void
+show_disconnect_pdu(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ gint length;
+ gint value;
+ proto_tree *acse_tree_pc = NULL;
+ proto_item *itu;
+ guint new_item_len;
+ guint start = *offset;
+ int save_len = item_len;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ *offset = asn->offset;
+ return;
+ }
+
+ if(item_len <= 0)
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Reason not specified");
+ *offset = asn->offset;
+ return;
+ }
+ itu = proto_tree_add_text(acse_tree, tvb, *offset,ABORT_REASON_LEN,
+ "Reason");
+ acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
+ (*offset)++; /* skip type */
+ asn->offset = *offset;
+ item_len--;
+ /* get length */
+ if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
+ ASN1_ERR_NOERROR)
+ {
+ *offset = asn->offset;
+ return;
+ }
+ /* try to get reason */
+ value = get_integer_value(asn,new_item_len,offset);
+
+ proto_tree_add_text(acse_tree_pc, tvb, *offset+1,new_item_len,
+ val_to_str(value,release_response_reason,"Unknown item (0x%02x)"));
+ item_len-=(asn->offset-*offset)+new_item_len;
+ *offset = asn->offset+new_item_len;
+ asn->offset = *offset;
+ /* do we have User information field ? */
+ if(item_len > 0)
+ {
+ show_acse_user_information(asn,acse_tree,tvb,offset,item_len);
+ }
+ /* align the pointer */
+ (*offset)=start+save_len;
+ asn->offset = (*offset);
+}
+
+static void
+show_finish_pdu(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ gint length;
+ gint value;
+ proto_tree *acse_tree_pc = NULL;
+ proto_item *itu;
+ guint new_item_len;
+ guint start = *offset;
+ int save_len = item_len;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ *offset = asn->offset;
+ return;
+ }
+
+ if(item_len <= 0)
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Reason not specified");
+ *offset = asn->offset;
+ return;
+ }
+ itu = proto_tree_add_text(acse_tree, tvb, *offset,ABORT_REASON_LEN,
+ "Reason");
+ acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
+ (*offset)++; /* skip type */
+ asn->offset = *offset;
+ item_len--;
+ /* get length */
+ if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
+ ASN1_ERR_NOERROR)
+ {
+ *offset = asn->offset;
+ return;
+ }
+ /* try to get reason */
+ value = get_integer_value(asn,new_item_len,offset);
+
+ proto_tree_add_text(acse_tree_pc, tvb, *offset+1,new_item_len,
+ val_to_str(value,release_request_reason,"Unknown item (0x%02x)"));
+ item_len-=(asn->offset-*offset)+new_item_len;
+ *offset = asn->offset+new_item_len;
+ asn->offset = *offset;
+ /* do we have User information field ? */
+ if(item_len > 0)
+ {
+ show_acse_user_information(asn,acse_tree,tvb,offset,item_len);
+ }
+ /* align the pointer */
+ (*offset)=start+save_len;
+ asn->offset = (*offset);
+}
+static void
+show_user_data(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *acse_tree_ud = NULL;
+ proto_tree *acse_tree_pc = NULL;
+ proto_item *itm;
+ proto_item *itu;
+ guint start = asn->offset;
+ guint item_length = item_len;
+
+ itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset -*offset)+
+ item_len, "User data");
+ acse_tree_ud = proto_item_add_subtree(itm, ett_acse_ms);
+ itu = proto_tree_add_text(acse_tree_ud, tvb,
+ *offset,item_len+(asn->offset-*offset),
+ val_to_str(tag, user_data_values_vals,"Unknown item (0x%02x)"));
+ acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
+ switch(tag)
+ {
+ case SIMPLY_ENCODED_DATA:
+ break;
+ case FULLY_ENCODED_DATA:
+ show_fully_encoded_data(asn,acse_tree_pc,tvb,offset,item_len);
+ break;
+ default:
+ break;
+ }
+
+
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+
+}
+
+/* if we can't dissect */
+static void
+dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const char *field_name, int ret)
+{
+ char *errstr;
+ errstr = asn1_err_to_str(ret);
+
+ if (tree != NULL)
+ {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "ERROR: Couldn't parse %s: %s", field_name, errstr);
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ }
+}
+
+/* display request top sequence */
+static void
+show_request_sequence_top(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, acse_tree,
+ "sequence error", ret);
+ break;
+ }
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case USER_INFORMATION:
+ show_acse_user_information(asn,acse_tree,tvb,offset,len1);
+ break;
+ case CALLED_AE_QUALIFIER:
+ case CALLING_AE_QUALIFIER:
+ {
+ proto_tree *acse_tree_pr = NULL;
+ proto_item *pr;
+ pr = proto_tree_add_text(acse_tree,tvb,*offset,
+ len1+(asn->offset-*offset),
+ val_to_str(tag ,request_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
+ show_integer(asn,acse_tree_pr,tvb,offset,len1);
+ }
+ break;
+ case APPLICATION_CONTEXT_NAME:
+ case CALLED_AP_TITLE:
+ case CALLING_AP_TITLE:
+ case CALLED_AP_INVOKATION_ID:
+ case CALLED_AE_INVOKATION_ID:
+ case CALLING_AP_INVOKATION_ID:
+ case CALLING_AE_INVOKATION_ID:
+ {
+ gchar oid_string[MAXSTRING];
+ show_oid(asn,acse_tree,tvb,offset,len1,(const
+value_string*)&request_sequence_top_vals,
+ (gchar*)&oid_string);
+ if(tag == APPLICATION_CONTEXT_NAME )
+ {
+ guint pos_in_string;
+ /* try to find real OID string from given */
+ /* function could return "1.0.8571.1.1" or "1.0.8571.1.1 iso.0.8571.1.1" */
+ /* so try to find first blank and strip string */
+ for(pos_in_string=0;pos_in_string<strlen(oid_string);pos_in_string++)
+ {
+ if( oid_string[pos_in_string] == ' ' )
+ {
+ oid_string[pos_in_string] = 0x00;
+ break;
+ }
+ }
+ /* try to get subdissector handler using given OID */
+ if(pos_in_string )
+ {
+ if( !(app_handle = dissector_get_string_handle(application_dissector_table, oid_string) ))
+ {
+ proto_tree_add_text(acse_tree,tvb,*offset,len1,"Unknown OID");
+ }
+ }
+ }
+ }
+ break;
+ case PROTOCOL_VERSION:
+ show_protocol_version(asn,acse_tree,tvb,offset,len1,tag);
+ break;
+ default:
+ itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset
+ -*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;;
+ }
+}
+/* display response top sequence */
+static void
+show_response_sequence_top(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, acse_tree,
+ "sequence error", ret);
+ break;
+ }
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case ACSE_RESULT:
+ show_acse_result(asn,acse_tree,tvb,offset,len1);
+ break;
+ case ACSE_RESULT_SOURCE_DIAGNOSTIC:
+ show_acse_result_source_diagnostic(asn,acse_tree,tvb,offset,len1);
+ break;
+ case USER_INFORMATION:
+ show_acse_user_information(asn,acse_tree,tvb,offset,len1);
+ break;
+
+ case RESPONDING_AE_QUALIFIER:
+ {
+ proto_tree *acse_tree_pr = NULL;
+ proto_item *pr;
+ pr = proto_tree_add_text(acse_tree,tvb,*offset,
+ len1+(asn->offset-*offset),
+ val_to_str(tag ,response_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
+ show_integer(asn,acse_tree_pr,tvb,offset,len1);
+ }
+ break;
+ case APPLICATION_CONTEXT_NAME:
+ case RESPONDING_AP_TITLE:
+ case RESPONDING_AP_INVOKATION_ID:
+ case RESPONDING_AE_INVOKATION_ID:
+ show_oid(asn,acse_tree,tvb,offset,len1,(const
+value_string*)&response_sequence_top_vals,NULL);
+ break;
+ case PROTOCOL_VERSION:
+ show_protocol_version(asn,acse_tree,tvb,offset,len1,tag);
+ break;
+ default:
+ itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset
+ -*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+/*
+* Dissect a pdu.
+*/
+static int
+dissect_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree
+ *tree)
+{
+ proto_item *ti;
+ proto_tree *acse_tree = NULL;
+ guint length;
+ guint rest_len;
+ guint s_type;
+ ASN1_SCK asn;
+ guint cp_type_len;
+/* get type of tag */
+ s_type = tvb_get_guint8(tvb, offset);
+ /* set up type of pdu */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(session->spdu_type, ses_vals, "Unknown pdu type (0x%02x)"));
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_acse, tvb, offset, -1,
+ FALSE);
+ acse_tree = proto_item_add_subtree(ti, ett_acse);
+ }
+ offset++;
+/* open asn.1 stream */
+ asn1_open(&asn, tvb, offset);
+
+ switch(session->spdu_type)
+ {
+ case SES_REFUSE:
+ case SES_CONNECTION_REQUEST:
+ case SES_CONNECTION_ACCEPT:
+ proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
+
+ if (read_length(&asn, acse_tree, hf_cp_type_message_length, &cp_type_len)
+ != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
+ )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(acse_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", cp_type_len,length);
+ }
+ return FALSE;
+ }
+ if(tree)
+ {
+ if(session->spdu_type == SES_CONNECTION_REQUEST)
+ {
+ show_request_sequence_top(&asn,acse_tree,tvb,pinfo,&offset,cp_type_len);
+ }
+ else
+ {
+ show_response_sequence_top(&asn,acse_tree,tvb,pinfo,&offset,cp_type_len);
+ }
+
+ }
+ break;
+ case SES_FINISH:
+ proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
+ /* get length */
+ if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < rest_len )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(acse_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", rest_len,length);
+ }
+ return FALSE;
+ }
+ show_finish_pdu(&asn,acse_tree,tvb,&offset,rest_len);
+ break;
+ case SES_DISCONNECT:
+ proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
+ /* get length */
+ if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < rest_len )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(acse_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", rest_len,length);
+ }
+ return FALSE;
+ }
+ show_disconnect_pdu(&asn,acse_tree,tvb,&offset,rest_len);
+ break;
+ case SES_ABORT:
+ proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
+ /* get length */
+ if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < rest_len )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(acse_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", rest_len,length);
+ }
+ return FALSE;
+ }
+ show_abort_reason(&asn,acse_tree,tvb,&offset,rest_len);
+ break;
+ default:
+ {
+ proto_item *ms;
+ proto_tree *acse_tree_ms = NULL;
+ /* back to length */
+ offset--;
+ /* get length */
+ if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ ms = proto_tree_add_text(acse_tree, tvb, offset, rest_len,
+ val_to_str(session->spdu_type, ses_vals, "Unknown pdu type (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ show_user_data(&asn,acse_tree_ms,tvb,&offset,rest_len,s_type);
+ }
+ }
+/* close asn.1 stream */
+ asn1_close(&asn, &offset);
+
+ return offset;
+}
+
+/*
+* Dissect ACSE PDUs inside a PPDU.
+*/
+static void
+dissect_acse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+/* first, try to check length */
+/* do we have at least 2 bytes */
+ if (!tvb_bytes_exist(tvb, 0, 2))
+ {
+ proto_tree_add_text(tree, tvb, offset,
+tvb_reported_length_remaining(tvb,offset),
+ "User data");
+ return; /* no, it isn't a ACSE PDU */
+ }
+/* do we have spdu type from the session dissector? */
+ if( !pinfo->private_data )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "Internal error:can't get spdu type from session dissector.");
+ return ;
+ }
+ }
+ else
+ {
+ session = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
+ if(session->spdu_type == 0 )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "Internal error:wrong spdu type %x from session dissector.",session->spdu_type);
+ return ;
+ }
+ }
+ }
+/* ACSE has only AARQ,AARE,RLRQ,RLRE,ABRT type of pdu */
+/* reject everything else */
+/* data pdu is not ACSE pdu and has to go directly to app dissector */
+ switch(session->spdu_type)
+ {
+ case SES_REFUSE: /* RLRE */
+ case SES_CONNECTION_REQUEST: /* AARQ */
+ case SES_CONNECTION_ACCEPT: /* AARE */
+ case SES_DISCONNECT: /* RLRQ */
+ case SES_FINISH: /* RLRE */
+ case SES_ABORT: /* ABRT */
+ break;
+ case SES_DATA_TRANSFER:
+ call_app_dissector(tvb,offset,tvb_reported_length_remaining(tvb, offset)
+,pinfo,tree,tree);
+ return;
+ default:
+ return;
+ }
+
+ /* we can't make any additional checking here */
+ /* postpone it before dissector will have more information */
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACSE");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+ /* save pointers for calling the app dissector */
+ global_tree = tree;
+ global_pinfo = pinfo;
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0)
+ {
+ offset = dissect_pdu(tvb, offset, pinfo, tree);
+ if(offset == FALSE )
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,"Internal error");
+ offset = tvb_length(tvb);
+ break;
+ }
+ }
+}
+
+void
+proto_register_acse(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_acse_type,
+ {
+ "PDU Type",
+ "acse.type",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(acse_vals),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_cp_type_message_length,
+ {
+ "Message Length",
+ "cp_type.message_length",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "CP type Message Length",
+ HFILL
+ }
+ },
+ {
+ &hf_protocol_version,
+ {
+ "Protocol version 1",
+ "acse.protocol.version",
+ FT_BOOLEAN, 16,
+ NULL,
+ ACSE_PROTOCOL_VERGION,
+ "Protocol version 1",
+ HFILL
+ }
+ },
+ };
+
+ static gint *ett[] =
+ {
+ &ett_acse,
+ &ett_acse_param,
+ &ett_acse_rc,
+ &ett_acse_ms,
+ &ett_acse_itm,
+ };
+ module_t *acse_module;
+
+
+ proto_acse = proto_register_protocol(PROTO_STRING_ACSE, "ACSE", "acse");
+ proto_register_field_array(proto_acse, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ acse_module = prefs_register_protocol(proto_acse, NULL);
+
+ /*
+ * Register the dissector by name, so other dissectors can
+ * grab it by name rather than just referring to it directly
+ */
+ register_dissector("acse", dissect_acse, proto_acse);
+ application_dissector_table = register_dissector_table("acse.application_context", "Application context OID", FT_STRING, BASE_NONE);
+}
+
+void
+proto_reg_handoff_acse(void)
+{
+ /* find data dissector */
+ data_handle = find_dissector("data");
+
+}
+
+