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 <[EMAIL PROTECTED]> To: Sid Sid <[EMAIL PROTECTED]> CC: [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 <[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-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 <[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_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; };
