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; };