Ethereal-dev: [Ethereal-dev] New OSI Session dissector.
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: "Sid Sid" <ysidelnikov@xxxxxxxxxxx>
Date: Mon, 27 Oct 2003 11:07:17 +0000
Hi,I've added some additional checking and used a value_string table where it makes sense.
Fixed casting to void and so on. Thanks. Yuriy.
From: Guy Harris <guy@xxxxxxxxxxxx> To: Sid Sid <ysidelnikov@xxxxxxxxxxx> CC: ethereal-dev@xxxxxxxxxxxx Subject: Re: [Ethereal-dev] New OSI Session dissector. Date: Fri, 26 Sep 2003 15:57:28 -0700 On Sep 25, 2003, at 1:01 PM, Sid Sid wrote:Please, have a look at attachment.It returns FALSE even if the packet is a session packet, except when it appears to return a number rather than a true/false value.The only check it does is to check whether the packet is at least 4 bytes long; that's not enough - that means that it could accept packets that aren't session-layer packets, which means that other heuristic dissectors for COTP, such as the SMB dissector, might not get a chance to check whether the packet is one of theirs.If it's not possible to have a good heuristic to check for OSI Session packets, perhaps the COTP dissector should try its heuristics and, if none of them match, try the session dissector.It also casts "dissect_ses" to a "void *", which hides the compiler errors that would have detected the original problem. Remove those casts, and either fix or remove the lines that get errors or warnings as a result of that change. (All the lines I saw could just be removed.)Note also that you have a number of places where you do a "switch()" on some value and select a constant string based on the value; that's probably best done using a value_string table - especially if the value has a field associated with it, because you can then associate that value_string table with the field._______________________________________________ Ethereal-dev mailing list Ethereal-dev@xxxxxxxxxxxx http://www.ethereal.com/mailman/listinfo/ethereal-dev
_________________________________________________________________MSN 8 helps eliminate e-mail viruses. Get 2 months FREE*. http://join.msn.com/?page=features/virus
/* packet-ses.c * * Routine to dissect ISO 8327-1 OSI Session Protocol packets * * $Id: packet-ses.c,v 1.00 2003/09/01 21:00:36 * * Yuriy Sidelnikov <YSidelnikov@xxxxxxxxxxx> * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> * 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-tpkt.h" #include "packet-ses.h" #include "packet-frame.h" #include "prefs.h" #include <epan/strutil.h> #include "etypes.h" /* ses header fields */ static int proto_ses = -1; static int hf_ses_version = -1; static int hf_ses_reserved = -1; static int hf_ses_length = -1; static proto_tree *ses_tree = NULL; /* ses fields defining a sub tree */ static gint ett_ses = -1;/* ----------------------------------------------------------------------------------------------------------*/
static dissector_handle_t pres_handle = NULL;/* ----------------------------------------------------------------------------------------------------------*/
/* flags */
static int hf_connect_protocol_options_flags = -1;
static int hf_session_user_req_flags = -1;
static int hf_version_number_options_flags = -1;
static int hf_enclosure_item_options_flags = -1;
static int hf_token_item_options_flags = -1;
static gint ett_connect_protocol_options_flags = -1;
static gint ett_protocol_version_flags = -1;
static gint ett_enclosure_item_flags = -1;
static gint ett_token_item_flags = -1;
static gint ett_ses_req_options_flags = -1;
static int able_to_receive_extended_concatenated_SPDU = -1;
static int half_duplex_function_unit = -1;
static int duplex_function_unit= -1;
static int session_exception_report= -1;
static int data_separation_function_unit= -1;
static int symmetric_syncronize_function_unit= -1;
static int typed_data_function_unit= -1;
static int exception_function_unit= -1;
static int negotiated_relese_function_unit= -1;
static int activity_management_function_unit= -1;
static int resyncronize_function_unit= -1;
static int major_resyncronize_function_unit= -1;
static int minor_resyncronize_function_unit= -1;
static int expedited_data_resyncronize_function_unit= -1;
static int capability_function_unit=-1;
/* protocol version */
static int protocol_version_1 = -1;
static int protocol_version_2 = -1;
/* enclosure item */
static int beginning_of_SSDU = -1;
static int end_of_SSDU = -1;
/* token item */
static int release_token = -1;
static int major_activity_token = -1;
static int syncronize_minor_token = -1;
static int data_token = -1;
static const value_string ses_vals[] =
{
{SES_CONNECTION_REQUEST, "Connection request PDU" },
{SES_CONNECTION_ACCEPT, "Connection accept PDU" },
{SES_EXCEPTION_REPORT, "Exception report PDU" },
{SES_DATA_TRANSFER, "Data transfer PDU" },
{SES_PLEASE_TOKENS, "Please tokens PDU" },
{SES_EXPEDITED, "Expedited PDU" },
{SES_PREPARE, "Prepare PDU" },
{SES_NOT_FINISHED, "Not finished PDU" },
{SES_FINISH, "Finish PDU" },
{SES_DISCONNECT, "Disconnect PDU" },
{SES_REFUSE, "Refuse PDU" },
{SES_CONNECTION_DATA_OVERFLOW, "Data overflow PDU" },
{SES_OVERFLOW_ACCEPT, "Overflow accept PDU" },
{SES_GIVE_TOKENS_CONFIRM, "Tokens confirm PDU" },
{SES_GIVE_TOKENS_ACK, "Give tokens ACK PDU" },
{SES_ABORT, "Abort PDU" },
{SES_ABORT_ACCEPT, "Abort accept PDU" },
{SES_ACTIVITY_RESUME, "Activity resume PDU" },
{SES_TYPED_DATA, "Typed data PDU" },
{SES_RESYNCHRONIZE_ACK, "Resynchronize ACK PDU" },
{SES_MAJOR_SYNC_POINT, "Session major sync point PDU" },
{SES_MAJOR_SYNC_ACK, "Session major sync ACK PDU" },
{SES_ACTIVITY_START, "Activity start PDU" },
{SES_EXCEPTION_DATA, "Exception data PDU" },
{SES_MINOR_SYNC_POINT, "Minor sync point PDU" },
{SES_MINOR_SYNC_ACK, "Minor sync ACK PDU" },
{SES_RESYNCHRONIZE, "Resynchronize PDU" },
{SES_ACTIVITY_DISCARD, "Activity discard PDU" },
{SES_ACTIVITY_DISCARD_ACK, "Activity discard ACK PDU" },
{SES_CAPABILITY, "Capability PDU" },
{SES_CAPABILITY_DATA_ACK, "Capability data ACK PDU" },
{0, NULL }
};
static const value_string reason_vals[] =
{
{reason_not_specified, "Reason Code: Rejection by called SS-user; reason
not specified" },
{temporary_congestion, "Reason Code: Rejection by called SS-user due to
temporary congestion" },
{Subsequent, "Reason Code: Rejection by called SS-user." },
{Session_Selector_unknown, "Reason Code: Session Selector unknown" },
{SS_user_not_attached_to_SSAP, "Reason Code: SS-user not attached to
SSAP" },
{SPM_congestion_at_connect_time, "Reason Code: SPM congestion at
connect time" },
{versions_not_supported, "Reason Code: Proposed protocol versions not
supported" },
{SPM_reason_not_specified, "Reason Code: Rejection by the SPM; reason
not specified" },
{SPM_implementation_restriction, "Finish PDU" },
{SES_DISCONNECT, "Reason Code: Rejection by the SPM; implementation
restriction stated in the PICS" },
{0, NULL }
};
/* desegmentation of OSI over ses */
/*static gboolean ses_desegment = TRUE;*/
/* find the dissector for data */
static dissector_handle_t data_handle;
/*static struct SES_PDU* reply_pdu;*/
/* function declaration */
int print_item(struct PGI_PI_UNIT* parms,tvbuff_t *tvb,int
offset,proto_tree *tree,packet_info *pinfo);
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;
}
/* this program returns length of session PDU */
int get_item_len(struct PGI_PI_UNIT* unit)
{
if( unit->len == TWO_BYTE_LEN)
{
struct CHAR_SHORT item_len;
item_len.data[0] = *( (((char*)(unit)) +2 ));
item_len.data[1] = *( (((char*)(unit)) +3 ));
return g_ntohs( item_len.short_data );
}
return unit->len;
}
/* this program returns address of next PGI/PI */
struct PGI_PI_UNIT* get_data_address(struct PGI_PI_UNIT* parms)
{
if( parms->len == TWO_BYTE_LEN)
{
return (struct PGI_PI_UNIT*) &parms->data1;
}
else
{
return (struct PGI_PI_UNIT*)&parms->data;
}
}
/* this program returns address of next PI item */
struct PGI_PI_UNIT* get_next_PI(struct PGI_PI_UNIT* parms)
{
if( parms->len == TWO_BYTE_LEN)
{
return (struct PGI_PI_UNIT*) (&parms->data1+get_item_len(parms) );
}
else
{
return (struct PGI_PI_UNIT*) (&parms->data+get_item_len(parms) );
}
}
int get_len_len(struct PGI_PI_UNIT* parms)
{
if( parms->len == TWO_BYTE_LEN)
{
return 4;
}
else
{
return 2;
}
}
int print_pgi(struct PGI_PI_UNIT* parm,tvbuff_t *tvb,int offset,proto_tree
*tree,packet_info *pinfo)
{
int res;
/* get total PGI data lenght */
int len = get_item_len(parm) ; /*- (get_len_len(parm)); */
/* get data address into PGI */
struct PGI_PI_UNIT* parms = get_data_address(parm);
offset = offset + get_len_len(parm);
while(len > 0)
{
if( (res = print_item( parms,tvb,offset,tree,pinfo) ) )
{
return res;
}
/* next item */
len = len - (get_item_len(parms)+get_len_len(parms)) ;
offset = offset + get_item_len(parms)+get_len_len(parms);
parms = get_next_PI(parms) ;
continue;
}
return FALSE;
}
int print_item(struct PGI_PI_UNIT* parms,tvbuff_t *tvb,int
offset,proto_tree *tree,packet_info *pinfo)
{
char tmp[MAXSTRING];
proto_item *tf;
gchar *reason_str;
int len = get_item_len((struct PGI_PI_UNIT*)parms);
switch(parms->type)
{
case Called_SS_user_Reference:
sprintf(tmp,"Called SS user Reference:");
break;
case Calling_SS_user_Reference:
sprintf(tmp,"Calling SS user Reference:");
break;
case Common_Reference:
sprintf(tmp,"Common Reference:");
break;
case Additional_Reference_Information:
sprintf(tmp,"Additional Reference Information:");
break;
case Sync_Type_Item:
sprintf(tmp,"Sync Type Item:");
break;
case Token_Item:
sprintf(tmp,"Token Item:");
if (tree)
{
guint8 flags = 0;
proto_tree *flags_tree=NULL;
proto_tree_add_text(ses_tree, tvb, offset, len+2,tmp);
flags = *( (guint8*) get_data_address(parms)) ;
tf = proto_tree_add_uint_format(ses_tree, hf_token_item_options_flags,
tvb, offset + 2, 1,
flags, "Flags: 0x%02x", flags); flags_tree = proto_item_add_subtree(tf, ett_token_item_flags);proto_tree_add_boolean(flags_tree, release_token, tvb, offset+2, 1, flags); proto_tree_add_boolean(flags_tree, major_activity_token, tvb, offset+2, 1, flags); proto_tree_add_boolean(flags_tree, syncronize_minor_token, tvb, offset+2, 1, flags); proto_tree_add_boolean(flags_tree, data_token, tvb, offset+2, 1, flags);
}
return FALSE;
case Transport_Disconnect:
sprintf(tmp,"Transport_Disconnect:");
if (tree)
{
proto_tree_add_text(ses_tree, tvb, offset,
1,"%s0x%02x",tmp,parms->type);
}
if(parms->data & transport_connection_is_released )
{
sprintf(tmp,"transport connection is released");
if (tree) proto_tree_add_text(ses_tree, tvb, offset+1, 1,tmp);
}
else
{
sprintf(tmp,"transport connection is kept");
if (tree) proto_tree_add_text(ses_tree, tvb, offset+1, 1,tmp);
}
if(parms->data & user_abort )
{
sprintf(tmp,"user abort");
if (tree) proto_tree_add_text(ses_tree, tvb, offset+1, 1,tmp);
}
if(parms->data & protocol_error )
{
sprintf(tmp,"protocol error");
if (tree) proto_tree_add_text(ses_tree, tvb, offset+1, 1,tmp);
}
if(parms->data & no_reason )
{
sprintf(tmp,"no reason");
if (tree) proto_tree_add_text(ses_tree, tvb, offset+1, 1,tmp);
}
if(parms->data & implementation_restriction )
{
sprintf(tmp,"implementation restriction");
if (tree) proto_tree_add_text(ses_tree, tvb, offset+1, 1,tmp);
}
return FALSE;
break;
case Protocol_Options:
sprintf(tmp,"Protocol Options:");
if (tree)
{
guint8 flags = 0;
proto_tree *flags_tree=NULL;
proto_tree_add_text(ses_tree, tvb, offset, len+2,tmp);
flags = *( (guint8*) get_data_address(parms)) ;
tf = proto_tree_add_uint_format(ses_tree,
hf_connect_protocol_options_flags, tvb, offset + 2, 1,
flags, "Flags: 0x%02x", flags);flags_tree = proto_item_add_subtree(tf, ett_connect_protocol_options_flags); proto_tree_add_boolean(flags_tree, able_to_receive_extended_concatenated_SPDU, tvb, offset+2, 1, flags);
}
return FALSE;
case TSDU_Maximum_Size:
sprintf(tmp,"TSDU Maximum Size:");
break;
case Version_Number:
sprintf(tmp,"Version Number:");
if (tree)
{
guint8 flags = 0;
proto_tree *flags_tree=NULL;
proto_tree_add_text(ses_tree, tvb, offset, len+2,tmp);
flags = *( (guint8*) get_data_address(parms)) ;
tf = proto_tree_add_uint_format(ses_tree,
hf_version_number_options_flags, tvb, offset + 2, 1,
flags, "Flags: 0x%02x", flags); flags_tree = proto_item_add_subtree(tf, ett_protocol_version_flags);proto_tree_add_boolean(flags_tree, protocol_version_2, tvb, offset+2, 1, flags); proto_tree_add_boolean(flags_tree, protocol_version_1, tvb, offset+2, 1, flags);
}
return FALSE;
case Initial_Serial_Number:
sprintf(tmp,"Initial Serial Number:");
break;
case Prepare_Type:
sprintf(tmp,"Prepare Type:");
break;
case EnclosureItem:
sprintf(tmp,"Enclosure Item:");
if (tree)
{
guint8 flags = 0;
proto_tree *flags_tree=NULL;
proto_tree_add_text(ses_tree, tvb, offset, len+2,tmp);
flags = *( (guint8*) get_data_address(parms)) ;
tf = proto_tree_add_uint_format(ses_tree,
hf_enclosure_item_options_flags, tvb, offset + 2, 1,
flags, "Flags: 0x%02x", flags); flags_tree = proto_item_add_subtree(tf, ett_enclosure_item_flags);proto_tree_add_boolean(flags_tree, end_of_SSDU, tvb, offset+2, 1, flags); proto_tree_add_boolean(flags_tree, beginning_of_SSDU, tvb, offset+2, 1, flags);
} return FALSE; case Token_Setting_Item: sprintf(tmp,"Token Setting Item:"); break; case Resync_Type: sprintf(tmp,"Resync Type:"); break; case Reason_Code: /* 0: Rejection by called SS-user; reason not specified. 1: Rejection by called SS-user due to temporary congestion.2: Rejection by called SS-user. Subsequent octets may be used for user data up to a length of 512 octets if Protocol Version 1 has been selected, and up to a length such that the total length (including SI and LI) of the SPDU does not exceed 65 539 octets if Protocol Version 2 has been selected.
128 + 1: Session Selector unknown. 128 + 2: SS-user not attached to SSAP. 128 + 3: SPM congestion at connect time. 128 + 4: Proposed protocol versions not supported. 128 + 5: Rejection by the SPM; reason not specified.128 + 6: Rejection by the SPM; implementation restriction stated in the PICS. */
if (!(reason_str = match_strval(parms->data, reason_vals)))
{
if (tree) proto_tree_add_text(ses_tree, tvb, offset, 2,"Reason Code:
Unknown %d",parms->data);
}
else
{
if (tree) proto_tree_add_text(ses_tree, tvb, offset, 2,reason_str);
}
/* do we have what to send to next dissector */
if (!tvb_bytes_exist(tvb, 0, 4))
return FALSE; /* No */
/* yes, call sub dissector. */
if(!pres_handle)
{
/* print as data */
offset = offset + get_len_len(parms);
call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
pinfo, tree);
offset += tvb_length_remaining(tvb, offset);
}
else
{
/* call presentation dissector */
tvbuff_t *next_tvb;
offset = offset + get_len_len(parms);
next_tvb = tvb_new_subset(tvb, offset, -1, -1);
TRY
{
call_dissector(pres_handle, next_tvb, pinfo, tree);
}
CATCH(BoundsError)
{
show_reported_bounds_error(tvb, pinfo, tree);
RETHROW;
}
CATCH(ReportedBoundsError)
{
show_reported_bounds_error(tvb, pinfo, tree);
}
ENDTRY;
} return parms->len-1;
break;
case Calling_Session_Selector:
sprintf(tmp,"Calling Session Selector:");
break;
case Called_Session_Selector:
sprintf(tmp,"Called Session Selector:");
break;
case Second_Resync_Type:
sprintf(tmp,"Second Resync Type:");
break;
case Second_Serial_Number:
sprintf(tmp,"Second Serial Number:");
break;
case Second_Initial_Serial_Number:
sprintf(tmp,"Second Initial Serial Number:");
break;
case Upper_Limit_Serial_Number:
sprintf(tmp,"Upper Limit Serial Number:");
break;
case Large_Initial_Serial_Number:
sprintf(tmp,"Large Initial Serial Number:");
break;
case Large_Second_Initial_Serial_Number:
sprintf(tmp,"Large Second Initial Serial Number:");
break;
case Data_Overflow:
sprintf(tmp,"Data Overflow:");
break;
case Session_Requirement:
sprintf(tmp,"Session Requirement:");
if (tree)
{
guint16 flags=0;
proto_tree *flags_tree=NULL;
struct CHAR_SHORT flg;
proto_tree_add_text(ses_tree, tvb, offset, len+2,tmp);
flg.data[0] = *( (guint8*) get_data_address(parms));
flg.data[1] = *( ((guint8*) get_data_address(parms)) +1);
flags = g_ntohs(flg.short_data) ;
tf = proto_tree_add_uint_format(ses_tree, hf_session_user_req_flags,
tvb, offset + 2, 2,
flags, "Flags: 0x%04x", flags); flags_tree = proto_item_add_subtree(tf, ett_ses_req_options_flags);proto_tree_add_boolean(flags_tree, session_exception_report, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, data_separation_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, symmetric_syncronize_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, typed_data_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, exception_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, capability_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, negotiated_relese_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, activity_management_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, resyncronize_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, major_resyncronize_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, minor_resyncronize_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, expedited_data_resyncronize_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, half_duplex_function_unit, tvb, offset+2, 2, flags); proto_tree_add_boolean(flags_tree, duplex_function_unit, tvb, offset+2, 2, flags);
}
return FALSE;
case Reflect_Parameter:
sprintf(tmp,"Reflect Parameter:");
break;
default:
sprintf(tmp,"Unknown session parameter:0x%02x",parms->type);
break;
}
if (tree)
{
char tm[MAXSTRING];
memset(&tm,0x00,sizeof(tmp));
string_to_hex( (unsigned char*)
get_data_address(parms),tm,get_item_len(parms));
proto_tree_add_text(ses_tree, tvb, offset,
get_len_len(parms)+get_item_len(parms),"%s0x%s",tmp,tm );
} return FALSE; }int print_ses_parameters(struct PGI_PI_UNIT* parm,int g_len,tvbuff_t *tvb,int offset,proto_tree *tree,packet_info *pinfo)
{
char tmp[MAXSTRING];
int res;
while(g_len > 0)
{
int len = get_item_len(parm);
if(parm->type == EXTENDED_USER_DATA )
{
sprintf(tmp,"Session extended user data:");
if (tree) proto_tree_add_text(ses_tree, tvb, offset+get_len_len(parm),
len,tmp);
return TRUE;
}
if(parm->type == SES_USER_DATA )
{
sprintf(tmp,"Session user data:");
/* do we have OSI presentation packet dissector ? */
if(!pres_handle)
{
/* print as data */
sprintf(tmp,"User data:");
if (tree) proto_tree_add_text(ses_tree, tvb, offset+get_len_len(parm),
len,tmp);
}
else
{
/* call presentation dissector */
tvbuff_t *next_tvb;
offset = offset + get_len_len(parm);
next_tvb = tvb_new_subset(tvb, offset, offset+get_len_len(parm),
len);
TRY
{
call_dissector(pres_handle, next_tvb, pinfo, tree);
}
CATCH(BoundsError)
{
show_reported_bounds_error(tvb, pinfo, tree);
RETHROW;
}
CATCH(ReportedBoundsError)
{
show_reported_bounds_error(tvb, pinfo, tree);
}
ENDTRY;
}
return TRUE;
}
/* is it PGI ? */
if(parm->type == Connect_Accept_Item
|| parm->type == Connection_Identifier
|| parm->type == Linking_Information )
{
switch(parm->type)
{
case Connect_Accept_Item:
sprintf(tmp,"Connect/Accept Item:0x%02x",parm->type);
if (tree) proto_tree_add_text(ses_tree, tvb, offset, get_item_len(
(struct PGI_PI_UNIT*) parm)+get_len_len((struct PGI_PI_UNIT*)parm),tmp);
break;
case Connection_Identifier:
sprintf(tmp,"Connection identifier:0x%02x",parm->type);
if (tree) proto_tree_add_text(ses_tree, tvb, offset, 1,tmp);
break;
case Linking_Information:
sprintf(tmp,"Linking information:0x%02x",parm->type);
if (tree) proto_tree_add_text(ses_tree, tvb, offset, 1,tmp);
break;
}
if( (res = print_pgi(parm,tvb,offset,tree,pinfo) ) )
{
return res;
}
g_len= g_len - (get_item_len(parm)+get_len_len(parm));
offset = offset + get_item_len(parm)+get_len_len(parm);
parm = get_next_PI( parm);
continue;
}
/* it should be PI */
if( (res = print_item( parm,tvb,offset,tree,pinfo)) )
{
return res;
}
g_len= g_len - (get_item_len(parm)+get_len_len(parm));
offset = offset + get_item_len(parm)+get_len_len(parm);
parm = get_next_PI( parm);
continue;
}
/* do we have what to send to next dissector */
if (!tvb_bytes_exist(tvb, 0, 4))
return FALSE; /* No */
/* yes, call sub dissector. */
if(!pres_handle)
{
/* print as data */
call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
pinfo, tree);
offset += tvb_length_remaining(tvb, offset);
}
else
{
/* call presentation dissector */
tvbuff_t *next_tvb;
offset = offset + get_len_len(parm);
next_tvb = tvb_new_subset(tvb, offset, -1, -1);
TRY
{
call_dissector(pres_handle, next_tvb, pinfo, tree);
}
CATCH(BoundsError)
{
show_reported_bounds_error(tvb, pinfo, tree);
RETHROW;
}
CATCH(ReportedBoundsError)
{
show_reported_bounds_error(tvb, pinfo, tree);
}
ENDTRY;
}
return FALSE;
}
int print_spdu(tvbuff_t *tvb,int offset,proto_tree *tree,packet_info *pinfo)
{
/* print length */
char tmp[MAXSTRING];
int total_len=0;
struct PGI_PI_UNIT* parms;
/* get total len of spdu */
unsigned char len_type = tvb_get_guint8(tvb, offset+1);
if( len_type == TWO_BYTE_LEN)
{
total_len = tvb_get_ntohs(tvb, offset+2);
sprintf(tmp,"User data len: 0x%02x",(total_len) );
if (tree) proto_tree_add_text(ses_tree, tvb, offset+1, 3,tmp);
parms = (struct PGI_PI_UNIT*) tvb_get_ptr(tvb, offset+4, total_len);
offset = offset + 4;
}
else
{
total_len = len_type;
sprintf(tmp,"User data len: 0x%x",(total_len) );
if (tree) proto_tree_add_text(ses_tree, tvb, offset+1, 1,tmp);
parms = (struct PGI_PI_UNIT*) tvb_get_ptr(tvb, offset+2, total_len);
offset = offset + 2;
}
return print_ses_parameters( parms,total_len,tvb,offset,tree,pinfo);
}
/*
* Dissect ses-encapsulated data in a SES stream.
*/
static void
dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
// char tmp[MAXSTRING];
proto_item *ti = NULL;
unsigned char type = 0;
volatile int offset = 0;
gchar *ses_str;
/* get SPDU type */
type = tvb_get_guint8(tvb, offset);
/* check SPDU type */
if (!(ses_str = match_strval(type, ses_vals)))
{
ses_str = "Unknown Spdu type";
}
ti = proto_tree_add_item(tree, proto_ses, tvb,offset, -1, FALSE);
ses_tree = proto_item_add_subtree(ti, ett_ses);
if (check_col(pinfo->cinfo, COL_INFO))
col_add_str(pinfo->cinfo, COL_INFO, "");
pinfo->current_proto = "SES";
if (check_col(pinfo->cinfo, COL_INFO))
col_add_str(pinfo->cinfo, COL_INFO, PROTO_STRING_SES_INFO);
if ( check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "SES");
if (check_col(pinfo->cinfo, COL_INFO))
col_add_str(pinfo->cinfo, COL_INFO, ses_str);
if (tree)
{
proto_tree_add_text(ses_tree, tvb, offset, 1,"%s:0x%02x",ses_str,type);
}
/* print session pdu */
print_spdu(tvb,offset,tree,pinfo);
return ;
}
void
proto_register_ses(void)
{
static hf_register_info hf[] =
{
{
&hf_ses_version,
{
"Version",
"ses.version",
FT_UINT8,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&hf_ses_reserved,
{
"Reserved",
"ses.reserved",
FT_UINT8,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&hf_ses_length,
{
"Length",
"ses.length",
FT_UINT16,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&expedited_data_resyncronize_function_unit,
{
"expedited data function unit",
"ses.expedited.data",
FT_BOOLEAN, 16,
NULL,
EXPEDITED_DATA_FUNCTION_UNIT,
"expedited data function unit",
HFILL
}
},
{
&minor_resyncronize_function_unit,
{
"minor resyncronize function unit",
"ses.minor.resyncronize",
FT_BOOLEAN, 16,
NULL,
MINOR_SYNCRONIZE_FUNCTION_UNIT,
"minor resyncronize function unit",
HFILL
}
},
{
&major_resyncronize_function_unit,
{
"major resyncronize function unit",
"ses.major.resyncronize",
FT_BOOLEAN, 16,
NULL,
MAJOR_SYNCRONIZE_FUNCTION_UNIT,
"major resyncronize function unit",
HFILL
}
},
{
&resyncronize_function_unit,
{
"resyncronize function unit",
"ses.resyncronize",
FT_BOOLEAN, 16,
NULL,
RESYNCRONIZE_FUNCTION_UNIT,
"resyncronize function unit",
HFILL
}
},
{
&activity_management_function_unit,
{
"activity management function unit",
"ses.activity.management",
FT_BOOLEAN, 16,
NULL,
ACTIVITY_MANAGEMENT_FUNCTION_UNIT,
"activity management function unit",
HFILL
}
},
{
&negotiated_relese_function_unit,
{
"negotiated relese function unit",
"ses.negotiated.relese",
FT_BOOLEAN, 16,
NULL,
NEGOTIATED_RELEASE_FUNCTION_UNIT,
"negotiated relese function unit",
HFILL
}
},
{
&capability_function_unit,
{
"capability function unit",
"ses.capability.data",
FT_BOOLEAN, 16,
NULL,
CAPABILITY_DATA_FUNCTION_UNIT,
"capability function unit",
HFILL
}
},
{
&exception_function_unit,
{
"exception function unit",
"ses.exception.data",
FT_BOOLEAN, 16,
NULL,
EXCEPTION_FUNCTION_UNIT,
"exception function unit",
HFILL
}
},
{
&typed_data_function_unit,
{
"typed data function unit",
"ses.typed.data",
FT_BOOLEAN, 16,
NULL,
TYPED_DATA_FUNCTION_UNIT,
"typed data function unit",
HFILL
}
},
{
&symmetric_syncronize_function_unit,
{
"symmetric syncronize function unit",
"ses.symm.sync",
FT_BOOLEAN, 16,
NULL,
SYMMETRIC_SYNCRONIZE_FUNCTION_UNIT,
"symmetric syncronize function unit",
HFILL
}
},
{
&data_separation_function_unit,
{
"data separation function unit",
"ses.data.sep",
FT_BOOLEAN, 16,
NULL,
DATA_SEPARATION_FUNCTION_UNIT,
"data separation function unit",
HFILL
}
},
{
&session_exception_report,
{
"session exception report",
"ses.exception.report.",
FT_BOOLEAN, 16,
NULL,
SES_EXCEPTION_REPORT,
"session exception report",
HFILL
}
},
{
&duplex_function_unit,
{
"half duplex functional unit",
"ses.duplex",
FT_BOOLEAN, 16,
NULL,
HALF_DUPLEX_FUNCTION_UNIT,
"half duplex functional unit",
HFILL
}
},
{
&half_duplex_function_unit,
{
"duplex functional unit",
"ses.half.duplex",
FT_BOOLEAN, 16,
NULL,
DUPLEX_FUNCTION_UNIT,
"duplex functional unit",
HFILL
}
},
{
&able_to_receive_extended_concatenated_SPDU,
{
"Able to receive extended concatenated SPDU",
"ses.connect.f1",
FT_BOOLEAN, 8,
NULL,
SES_EXT_CONT,
"Able to receive extended concatenated SPDU",
HFILL
}
},
{
&beginning_of_SSDU,
{
"beginning of SSDU",
"ses.begininng.SPDU",
FT_BOOLEAN, 8,
NULL,
BEGINNING_SPDU,
"beginning of SSDU",
HFILL
}
},
{
&end_of_SSDU,
{
"end of SSDU",
"ses.end.SPDU",
FT_BOOLEAN, 8,
NULL,
END_SPDU,
"end of SSDU",
HFILL
}
},
{
&major_activity_token,
{
"major/activity token",
"ses.major.token",
FT_BOOLEAN, 8,
NULL,
MAJOR_ACTIVITY_TOKEN,
"major/activity token",
HFILL
}
},
{
&syncronize_minor_token,
{
"syncronize minor token",
"ses.syncronize.token",
FT_BOOLEAN, 8,
NULL,
SYNCRONIZE_MINOR_TOKEN,
"syncronize minor token",
HFILL
}
},
{
&data_token,
{
"data token",
"ses.data.token",
FT_BOOLEAN, 8,
NULL,
DATA_TOKEN,
"data token",
HFILL
}
},
{
&release_token,
{
"release token",
"ses.release.token",
FT_BOOLEAN, 8,
NULL,
RELEASE_TOKEN,
"release token",
HFILL
}
},
{
&protocol_version_1,
{
"Protocol Version 1",
"ses.protocol.version2",
FT_BOOLEAN, 8,
NULL,
PROTOCOL_VERSION_1,
"Protocol Version 1",
HFILL
}
},
{
&protocol_version_2,
{
"Protocol Version 2",
"ses.protocol.version2",
FT_BOOLEAN, 8,
NULL,
PROTOCOL_VERSION_2,
"Protocol Version 2",
HFILL
}
},
{
&hf_connect_protocol_options_flags,
{
"Flags",
"ses.connect.flags",
FT_UINT8,
BASE_HEX,
NULL,
0x0,
"",
HFILL
}
},
{
&hf_version_number_options_flags,
{
"Flags",
"ses.version.flags",
FT_UINT8,
BASE_HEX,
NULL,
0x0,
"",
HFILL
}
},
{
&hf_token_item_options_flags,
{
"Flags",
"ses.tken_item.flags",
FT_UINT8,
BASE_HEX,
NULL,
0x0,
"",
HFILL
}
},
{
&hf_enclosure_item_options_flags,
{
"Flags",
"ses.enclosure.flags",
FT_UINT8,
BASE_HEX,
NULL,
0x0,
"",
HFILL
}
},
{
&hf_session_user_req_flags,
{
"Flags",
"ses.req.flags",
FT_UINT16,
BASE_HEX,
NULL,
0x0,
"",
HFILL
}
},
};
static gint *ett[] =
{
&ett_ses,
&ett_connect_protocol_options_flags,
&ett_protocol_version_flags,
&ett_enclosure_item_flags,
&ett_token_item_flags,
&ett_ses_req_options_flags,
};
module_t *ses_module;
proto_ses = proto_register_protocol(PROTO_STRING_SES, "SES", "ses");
proto_register_field_array(proto_ses, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
ses_module = prefs_register_protocol(proto_ses, NULL);
/*
prefs_register_bool_preference(ses_module, "desegment",
"Desegment all session packets ",
"Whether the ses dissector should desegment all messages spanning
multiple SES segments",
&ses_desegment); */
/*
* Register the dissector by name, so other dissectors can
* grab it by name rather than just referring to it directly
* (you can't refer to it directly from a plugin dissector
* on Windows without stuffing it into the Big Transfer Vector).
*/
register_dissector("ses", dissect_ses, proto_ses);
}
static gboolean
dissect_ses_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
/* must check that this really is a ses packet */
unsigned char type = 0;
volatile int offset = 0;
int len=0;
struct PGI_PI_UNIT* parms;
gchar *ses_str;
/* first, check do we have at least 4 bytes */
if (!tvb_bytes_exist(tvb, 0, 4))
return FALSE; /* no */
/* OK,let's check SPDU length */
/* get at least 4 bytes */
parms = (struct PGI_PI_UNIT*) tvb_get_ptr(tvb, offset, 4);
/* get length of SPDU */
len = get_item_len((struct PGI_PI_UNIT*)parms);
/* do we have enough bytes ? */
if (!tvb_bytes_exist(tvb, 0, len))
return FALSE; /* no */
/* can we regognize session PDU ? Return FALSE if not */
/* get SPDU type */
type = tvb_get_guint8(tvb, offset);
/* check SPDU type */
if (!(ses_str = match_strval(type, ses_vals)))
{
return FALSE; /* no, it isn't a session PDU */
}
dissect_ses(tvb, pinfo, parent_tree);
return TRUE;
}
void
proto_reg_handoff_ses(void)
{
dissector_handle_t ses_handle;
/* find data dissector */
data_handle = find_dissector("data");
ses_handle = create_dissector_handle(dissect_ses, proto_ses);
/* define sub dissector */
pres_handle = find_dissector("pres");
/* add our session dissector to cotp dissector list */
heur_dissector_add("cotp", dissect_ses_heur, proto_ses);
}
/* packet-ses.h * * Routine to dissect ISO 8327-1 OSI Session Protocol packets * * * $Id: packet-ses.h,v 1.0 2003/09/01 21:00:36 * Yuriy Sidelnikov <YSidelnikov@xxxxxxxxxxx> * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> * 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_SES "ISO 8327-1 OSI Session Protocol" #define PROTO_STRING_SES_INFO "ISO 8327-1 OSI Session Protocol." /* * Dissect ses-encapsulated data in a TCP stream. */ static void dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); /* max string lenght */ #define MAXSTRING 1024 /* session parms*/ #define SES_EXT_CONT 0x01 /* protocol versions */ #define PROTOCOL_VERSION_1 0x01 #define PROTOCOL_VERSION_2 0x02 /* enclosure item */ #define BEGINNING_SPDU 0x01 #define END_SPDU 0x02 #define DATA_TOKEN 0x01 #define RELEASE_TOKEN 0x40 #define SYNCRONIZE_MINOR_TOKEN 0x04 #define MAJOR_ACTIVITY_TOKEN 0x10 /* session user req flag */ #define HALF_DUPLEX_FUNCTION_UNIT 0x0001 #define DUPLEX_FUNCTION_UNIT 0x0002 #define EXPEDITED_DATA_FUNCTION_UNIT 0x0004 #define MINOR_SYNCRONIZE_FUNCTION_UNIT 0x0008 #define MAJOR_SYNCRONIZE_FUNCTION_UNIT 0x0010 #define RESYNCRONIZE_FUNCTION_UNIT 0x0020 #define ACTIVITY_MANAGEMENT_FUNCTION_UNIT 0x0040 #define NEGOTIATED_RELEASE_FUNCTION_UNIT 0x0080 #define CAPABILITY_DATA_FUNCTION_UNIT 0x0100 #define EXCEPTION_FUNCTION_UNIT 0x0200 #define TYPED_DATA_FUNCTION_UNIT 0x0400 #define SYMMETRIC_SYNCRONIZE_FUNCTION_UNIT 0x0800 #define DATA_SEPARATION_FUNCTION_UNIT 0x1000 #define SES_EXCEPTION_REPORT 0x2000 /*define SES_EXCEPTION_REPORT 0 */ #define SES_DATA_TRANSFER 1 #define SES_GIVE_TOKEN 1 #define SES_PLEASE_TOKENS 2 #define SES_EXPEDITED 5 #define SES_PREPARE 7 #define SES_NOT_FINISHED 8 #define SES_FINISH 9 #define SES_DISCONNECT 10 #define SES_REFUSE 12 #define SES_CONNECTION_REQUEST 13 #define SES_CONNECTION_ACCEPT 14 #define SES_CONNECTION_DATA_OVERFLOW 15 #define SES_OVERFLOW_ACCEPT 16 #define SES_GIVE_TOKENS_CONFIRM 21 #define SES_GIVE_TOKENS_ACK 22 #define SES_ABORT 25 #define SES_ABORT_ACCEPT 26 /*#define SES_ACTIVITY_INTERRUPT 25 #define SES_ACTIVITY_INTERRUPT_ACK 26 */ #define SES_ACTIVITY_RESUME 29 #define SES_TYPED_DATA 33 #define SES_RESYNCHRONIZE_ACK 34 #define SES_MAJOR_SYNC_POINT 41 /*#define SES_MAJOR_SYNC_POINT 41 #define SES_ACTIVITY_END 41 */ #define SES_MAJOR_SYNC_ACK 42 #define SES_ACTIVITY_START 45 #define SES_EXCEPTION_DATA 48 #define SES_MINOR_SYNC_POINT 49 #define SES_MINOR_SYNC_ACK 50 #define SES_RESYNCHRONIZE 53 #define SES_ACTIVITY_DISCARD 57 #define SES_ACTIVITY_DISCARD_ACK 58 #define SES_CAPABILITY 61 #define SES_CAPABILITY_DATA_ACK 62 #define EXTENDED_USER_DATA 192 #define SES_USER_DATA 193 /* reason code 0: Rejection by called SS-user; reason not specified. 1: Rejection by called SS-user due to temporary congestion.2: Rejection by called SS-user. Subsequent octets may be used for user data up to a length of 512 octets if Protocol Version 1 has been selected, and up to a length such that the total length (including SI and LI) of the SPDU does not exceed 65 539 octets if Protocol Version 2 has been selected.
128 + 1: Session Selector unknown. 128 + 2: SS-user not attached to SSAP. 128 + 3: SPM congestion at connect time. 128 + 4: Proposed protocol versions not supported. 128 + 5: Rejection by the SPM; reason not specified.128 + 6: Rejection by the SPM; implementation restriction stated in the PICS.
*/
#define reason_not_specified 0
#define temporary_congestion 1
#define Subsequent 2
#define Session_Selector_unknown 128+1
#define SS_user_not_attached_to_SSAP 128+2
#define SPM_congestion_at_connect_time 128+3
#define versions_not_supported 128+4
#define SPM_reason_not_specified 128+5
#define SPM_implementation_restriction 128+6
#define TWO_BYTE_LEN 0xff
/* PGI */
#define Connection_Identifier 1
#define Connect_Accept_Item 5
#define Linking_Information 33
#define Called_SS_user_Reference 9
#define Calling_SS_user_Reference 10
#define Common_Reference 11
#define Additional_Reference_Information 12
#define Sync_Type_Item 15
#define Token_Item 16
#define Transport_Disconnect 17
#define Protocol_Options 19
#define Session_Requirement 20
#define TSDU_Maximum_Size 21
#define Version_Number 22
#define Initial_Serial_Number 23
#define Prepare_Type 24
#define EnclosureItem 25
#define Token_Setting_Item 26
#define Resync_Type 27
#define Reflect_Parameter 49
#define Reason_Code 50
#define Calling_Session_Selector 51
#define Called_Session_Selector 52
#define Second_Resync_Type 53
#define Second_Serial_Number 54
#define Second_Initial_Serial_Number 55
#define Upper_Limit_Serial_Number 56
#define Large_Initial_Serial_Number 57
#define Large_Second_Initial_Serial_Number 58
#define CALLED_SESSION_SELECTOR 0x33
#define CALLING_SESSION_SELECTOR 0x34
#define SES_USER_DATA 193
#define Data_Overflow 60
#define SES_PDU_HEADER_LEN 2
#define SES_DATA 0x01
// transport disconnect values
#define transport_connection_is_released 0x01
#define user_abort 0x02
#define protocol_error 0x04
#define no_reason 0x08
#define implementation_restriction 0x10
struct SES_PDU
{
unsigned char type;
unsigned char len;
union {
unsigned short len_short;
unsigned char data;
};
unsigned char data1;
};
struct PGI_PI_UNIT
{
unsigned char type;
unsigned char len;
union {
unsigned short len_short;
unsigned char data;
};
unsigned char data1;
};
struct CHAR_SHORT
{
union {
unsigned short short_data;
unsigned char data[2];
};
};
struct SES_PDU_PARM
{
unsigned char parm_type;
unsigned char len;
unsigned char data;
};
- Prev by Date: RE: [Ethereal-dev] reorganizing source tree
- Next by Date: Re: [Ethereal-dev] Display filter as stop condition
- Previous by thread: Re: [Ethereal-dev] Ethereal filters are case sensitive
- Next by thread: [Ethereal-dev] Patch epan/proto.c - proto_tree_append_string()
- Index(es):





