new OSI ACSE protocol dissector. Will work correctly only with today patch to presentation dissector.
Thank you. Yuriy Sidelnikov.
_________________________________________________________________
MSN 8 helps eliminate e-mail viruses. Get 2 months FREE*. http://join.msn.com/?page=features/virus /* packet-acse.c
*
* Routine to dissect OSI ACSE Protocol packets
*
*
*
* Yuriy Sidelnikov <[EMAIL PROTECTED]>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <[EMAIL PROTECTED]>
* 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;
/* ----------------------------------------------------------------------------------------------------------*/ static dissector_handle_t ftam_handle = NULL; static dissector_handle_t cmip_handle = NULL; 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 int type_of_application = 0;
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, int offset, guint16 param_len,
packet_info *pinfo, proto_tree *tree, proto_tree *param_tree)
{
char* name_of_app_dissect;
name_of_app_dissect = val_to_str(type_of_application, type_app,"Unknown type of application dissector (0x%02x)");
/* do we have OSI app packet dissector ? */
if(!app_handle || !type_of_application)
{
/* No - display as data */ if (tree) { proto_tree_add_text(param_tree, tvb, offset, param_len, "%s dissector is not available",name_of_app_dissect); } } 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(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,int 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((char*)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; gint length; guint type; guint header_len; proto_item *ms; gint 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)) < 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; gint 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; gint 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; gint 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; unsigned char ftam_oid[] = "1.0.8571.1.1"; unsigned char cmip_oid[] ="2.9.0.0.2";
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 )
{
if( !strcmp(oid_string,cmip_oid) )
{
/* it is CMIP */
type_of_application = CMIP_APP;
app_handle = cmip_handle;
}
else
if( !strcmp(oid_string,ftam_oid) )
{
/* it is CMIP */
type_of_application = FTAM_APP;
app_handle = ftam_handle;
}
else
{
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); }
void proto_reg_handoff_acse(void) { /* find data dissector */ data_handle = find_dissector("data"); /* define ftam sub dissector */ ftam_handle = find_dissector("ftam"); /* define cmip sub dissector */ cmip_handle = find_dissector("cmip");
}
/* packet-acse.h
*
* Routine to dissect OSI ISO/IEC 10035-1 ACSE Protocol packets
*
*
*
* Yuriy Sidelnikov <[EMAIL PROTECTED]>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <[EMAIL PROTECTED]>
* 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.
*/
#define PROTO_STRING_ACSE "OSI ISO/IEC 10035-1 ACSE Protocol" #define PROTO_STRING_ACSE_INFO "OSI ISO/IEC 10035-1 ACSE Protocol"
/* asn.1 definitions */ #define ASN1_CLASS_UNIVERSAL 0x00 #define ASN1_CLASS_APPLICATION 0x40 #define ASN1_CLASS_CONTEXT_SPECIFIC 0x80 #define ASN1_CLASS_Private 0xc0 #define ASN1_CLASS_PC 0x20
#define INTEGER_ITEM 0x01 #define BOOLEAN_ITEM 0x01
/* type of parameters */ #define MODE_SELECTOR 0 #define SET_TOP 1 #define SEQUENCE_TOP 2
#define SEQUENCE 0x30
/* sequence top */ #define TAG_00 0 #define TAG_01 1
enum { ACSE_AARQ = 0x60, ACSE_AARE, ACSE_RLRQ, ACSE_RLRE, ACSE_ABRT };
enum { PROTOCOL_VERSION, APPLICATION_CONTEXT_NAME, CALLED_AP_TITLE, CALLED_AE_QUALIFIER, CALLED_AP_INVOKATION_ID, CALLED_AE_INVOKATION_ID, CALLING_AP_TITLE, CALLING_AE_QUALIFIER, CALLING_AP_INVOKATION_ID, CALLING_AE_INVOKATION_ID, };
#define IMPLEMENTATION_INFORMATION 29 #define USER_INFORMATION 30 #define ACSE_EXTERNAL 8
enum { PROTOCOL_VERSION_2, APPLICATION_CONTEXT_NAME_2, ACSE_RESULT, ACSE_RESULT_SOURCE_DIAGNOSTIC, RESPONDING_AP_TITLE, RESPONDING_AE_QUALIFIER, RESPONDING_AP_INVOKATION_ID, RESPONDING_AE_INVOKATION_ID, };
enum { ACSE_NULL, ACSE_NO_REASON_GIVEN, ACSE_APPLICATION_CONTEXT_NAME_NOT_SUPPORTED, ACSE_CALLING_AP_TITLE_NOT_RECOGNIZED, ACSE_CALLING_AP_INVOKATION_IDENTIFIER_NOT_RECOGNIZED, ACSE_CALLING_AE_QUALIFIER_NOT_RECOGNIZED, ACSE_CALLING_AE_INVOKATION_IDENTIFIER_NOT_RECOGNIZED, ACSE_CALLED_AP_TITLE_NOT_RECOGNIZED, ACSE_CALLED_AP_INVOKATION_IDENTIFIER_NOT_RECOGNIZED, ACSE_CALLED_AE_QUALIFIER_NOT_RECOGNIZED, ACSE_CALLED_AE_INVOKATION_IDENTIFIER_NOT_RECOGNIZED, };
#define ACSE_NO_COMMON_ACSE_VERSION 2
#define ACSE_SERVICE_USER 1 #define ACSE_SERVICE_PROVIDER 2 #define ACSE_EXTERNAL_USER 8
//////////////////////////////////////////////////// //enum //{ //PROTOCOL_VERSION_1, //CALLING_PRESENTATION_SELECTOR, //CALLED_PRESENTATION_SELECTOR, //RESPONDING_PRESENTATION_SELECTOR, //PRESENTATION_CONTEXT_DEFINITION_LIST, //PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST, //DEFAULT_CONTEXT_NAME, //DEFAULT_CONTEXT_RESULT, //PRESENTATION_REQUIREMENTS, //USER_SESSION_REQUIREMENTS, //PROVIDER_REASON //}; /////////////////////////////////////////////////
/* definition list **/ #define PRESENTATION_CONTEXT_IDENTIFIER 2 #define ABSTRACT_SYNTAX_NAME 6 #define TRANSFER_SYNTAX_NAMES 0x30 /* result list */ #define PRESENTATION_RESULT 0x80 #define PRESENTATION_RESULT_TRANSFER_SYNTAX_NAME 0x81 #define PRESENTATION_RESULT_INTEGER 0x82
/* result values */ #define PRESENTATION_RESULT_ACCEPTANCE 0 #define PRESENTATION_RESULT_USER_REJECTION 1 #define PRESENTATION_RESULT_PROVIDER_REJECTION 2
enum { RRR_NORMAL, RRR_URGENT, RRR_USER_DEFINED, }; enum { RRPR_NORMAL, RRPR_URGENT, RRPR_USER_DEFINED }; enum { ABRT_ACSE_SERVICE_USER, ABRT_ACSE_SERVICE_PROVIDER, }; /* user data */ #define SIMPLY_ENCODED_DATA 0x60 #define FULLY_ENCODED_DATA 0x61
/* PDV */ #define SINGLE_ASN1_TYPE 0xa0 #define OCTET_ALIGNED 0xa1 #define ARBITRARY 0xa2
#define ACSE_PROTOCOL_VERGION 0x0080 #define MAXSTRING 256 #define ABORT_REASON_LEN 3
#define FTAM_APP 1 #define CMIP_APP 2
_______________________________________________ Ethereal-dev mailing list [EMAIL PROTECTED] http://www.ethereal.com/mailman/listinfo/ethereal-dev