2005-09-04 16:22:12 +00:00
/* packet-rtse_asn1.c
* Routines for RTSE packet dissection
* Graeme Lunt 2005
*
2006-05-21 05:12:17 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
2005-09-04 16:22:12 +00:00
* 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
2012-06-28 22:56:06 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
2005-09-04 16:22:12 +00:00
*/
2012-09-20 01:29:52 +00:00
# include "config.h"
2005-09-04 16:22:12 +00:00
# include <glib.h>
# include <epan/packet.h>
# include <epan/conversation.h>
2007-06-24 05:28:27 +00:00
# include <epan/prefs.h>
# include <epan/reassemble.h>
2007-05-13 20:58:29 +00:00
# include <epan/asn1.h>
2009-05-20 09:29:22 +00:00
# include <epan/expert.h>
2005-09-04 16:22:12 +00:00
# include "packet-ber.h"
# include "packet-pres.h"
# include "packet-acse.h"
# include "packet-ros.h"
# include "packet-rtse.h"
# define PNAME "X.228 OSI Reliable Transfer Service"
# define PSNAME "RTSE"
# define PFNAME "rtse"
2013-12-08 16:40:49 +00:00
void proto_register_rtse ( void ) ;
void proto_reg_handoff_rtse ( void ) ;
2005-09-04 16:22:12 +00:00
/* Initialize the protocol and registered fields */
2009-10-11 16:24:29 +00:00
static int proto_rtse = - 1 ;
2005-09-04 16:22:12 +00:00
2005-11-16 07:13:12 +00:00
static gboolean open_request = FALSE ;
2005-09-04 16:22:12 +00:00
static guint32 app_proto = 0 ;
static proto_tree * top_tree = NULL ;
2007-06-24 05:28:27 +00:00
/* Preferences */
static gboolean rtse_reassemble = TRUE ;
2005-09-04 16:22:12 +00:00
# include "packet-rtse-hf.c"
/* Initialize the subtree pointers */
static gint ett_rtse = - 1 ;
# include "packet-rtse-ett.c"
2013-06-03 03:42:36 +00:00
static expert_field ei_rtse_dissector_oid_not_implemented = EI_INIT ;
static expert_field ei_rtse_unknown_rtse_pdu = EI_INIT ;
2005-09-04 16:22:12 +00:00
static dissector_table_t rtse_oid_dissector_table = NULL ;
static GHashTable * oid_table = NULL ;
static gint ett_rtse_unknown = - 1 ;
2013-03-22 23:59:54 +00:00
static reassembly_table rtse_reassembly_table ;
2010-08-24 15:09:11 +00:00
static int hf_rtse_segment_data = - 1 ;
2007-06-24 05:28:27 +00:00
static int hf_rtse_fragments = - 1 ;
static int hf_rtse_fragment = - 1 ;
static int hf_rtse_fragment_overlap = - 1 ;
static int hf_rtse_fragment_overlap_conflicts = - 1 ;
static int hf_rtse_fragment_multiple_tails = - 1 ;
static int hf_rtse_fragment_too_long_fragment = - 1 ;
static int hf_rtse_fragment_error = - 1 ;
2011-01-30 21:01:07 +00:00
static int hf_rtse_fragment_count = - 1 ;
2007-06-24 05:28:27 +00:00
static int hf_rtse_reassembled_in = - 1 ;
2010-02-02 16:01:52 +00:00
static int hf_rtse_reassembled_length = - 1 ;
2007-06-24 05:28:27 +00:00
static gint ett_rtse_fragment = - 1 ;
static gint ett_rtse_fragments = - 1 ;
static const fragment_items rtse_frag_items = {
/* Fragment subtrees */
& ett_rtse_fragment ,
& ett_rtse_fragments ,
/* Fragment fields */
& hf_rtse_fragments ,
& hf_rtse_fragment ,
& hf_rtse_fragment_overlap ,
& hf_rtse_fragment_overlap_conflicts ,
& hf_rtse_fragment_multiple_tails ,
& hf_rtse_fragment_too_long_fragment ,
& hf_rtse_fragment_error ,
2011-01-30 21:01:07 +00:00
& hf_rtse_fragment_count ,
2007-06-24 05:28:27 +00:00
/* Reassembled in field */
& hf_rtse_reassembled_in ,
2010-02-02 16:01:52 +00:00
/* Reassembled length field */
& hf_rtse_reassembled_length ,
2012-09-10 15:24:00 +00:00
/* Reassembled data field */
NULL ,
2007-06-24 05:28:27 +00:00
/* Tag */
" RTSE fragments "
} ;
2005-09-04 16:22:12 +00:00
void
2008-11-04 21:50:33 +00:00
register_rtse_oid_dissector_handle ( const char * oid , dissector_handle_t dissector , int proto , const char * name , gboolean uses_ros )
2005-09-04 16:22:12 +00:00
{
2008-11-04 21:50:33 +00:00
/* XXX: Note that this fcn is called from proto_reg_handoff in *other* dissectors ... */
static dissector_handle_t rtse_handle = NULL ;
static dissector_handle_t ros_handle = NULL ;
if ( rtse_handle = = NULL )
rtse_handle = find_dissector ( " rtse " ) ;
if ( ros_handle = = NULL )
ros_handle = find_dissector ( " ros " ) ;
2005-10-24 21:42:19 +00:00
/* save the name - but not used */
g_hash_table_insert ( oid_table , ( gpointer ) oid , ( gpointer ) name ) ;
/* register RTSE with the BER (ACSE) */
register_ber_oid_dissector_handle ( oid , rtse_handle , proto , name ) ;
if ( uses_ros ) {
/* make sure we call ROS ... */
dissector_add_string ( " rtse.oid " , oid , ros_handle ) ;
/* and then tell ROS how to dissect the AS*/
register_ros_oid_dissector_handle ( oid , dissector , proto , name , TRUE ) ;
} else {
/* otherwise we just remember how to dissect the AS */
dissector_add_string ( " rtse.oid " , oid , dissector ) ;
}
2005-09-04 16:22:12 +00:00
}
static int
2013-11-05 18:47:26 +00:00
call_rtse_oid_callback ( const char * oid , tvbuff_t * tvb , int offset , packet_info * pinfo , proto_tree * tree , void * data )
2005-09-04 16:22:12 +00:00
{
tvbuff_t * next_tvb ;
2013-02-19 23:17:07 +00:00
next_tvb = tvb_new_subset_remaining ( tvb , offset ) ;
2013-11-05 18:47:26 +00:00
if ( ! dissector_try_string ( rtse_oid_dissector_table , oid , next_tvb , pinfo , tree , data ) ) {
2009-05-20 09:29:22 +00:00
proto_item * item = proto_tree_add_text ( tree , next_tvb , 0 , tvb_length_remaining ( tvb , offset ) , " RTSE: Dissector for OID:%s not implemented. Contact Wireshark developers if you want this supported " , oid ) ;
proto_tree * next_tree = proto_item_add_subtree ( item , ett_rtse_unknown ) ;
2005-09-04 16:22:12 +00:00
2013-09-09 00:28:48 +00:00
expert_add_info_format ( pinfo , item , & ei_rtse_dissector_oid_not_implemented ,
2009-05-20 09:29:22 +00:00
" RTSE: Dissector for OID %s not implemented " , oid ) ;
2005-09-04 16:22:12 +00:00
dissect_unknown_ber ( pinfo , next_tvb , offset , next_tree ) ;
}
2012-09-10 15:24:00 +00:00
/*XXX until we change the #.REGISTER signature for _PDU()s
2005-09-04 16:22:12 +00:00
* into new_dissector_t we have to do this kludge with
* manually step past the content in the ANY type .
*/
offset + = tvb_length_remaining ( tvb , offset ) ;
return offset ;
}
2007-11-14 20:57:55 +00:00
static int
call_rtse_external_type_callback ( gboolean implicit_tag _U_ , tvbuff_t * tvb , int offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index _U_ )
{
const char * oid = NULL ;
2013-11-05 18:47:26 +00:00
if ( actx - > external . indirect_ref_present ) {
2007-11-14 20:57:55 +00:00
oid = ( const char * ) find_oid_by_pres_ctx_id ( actx - > pinfo , actx - > external . indirect_reference ) ;
} else if ( actx - > external . direct_ref_present ) {
2013-11-05 18:47:26 +00:00
oid = actx - > external . direct_reference ;
2007-11-14 20:57:55 +00:00
}
if ( oid )
2013-11-05 18:47:26 +00:00
offset = call_rtse_oid_callback ( oid , tvb , offset , actx - > pinfo , top_tree ? top_tree : tree , actx - > private_data ) ;
2007-11-14 20:57:55 +00:00
return offset ;
}
2005-09-04 20:30:31 +00:00
# include "packet-rtse-fn.c"
2005-09-04 16:22:12 +00:00
/*
* Dissect RTSE PDUs inside a PPDU .
*/
2013-11-05 18:47:26 +00:00
static int
dissect_rtse ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * parent_tree , void * data )
2005-09-04 16:22:12 +00:00
{
int offset = 0 ;
int old_offset ;
2013-11-05 18:47:26 +00:00
proto_item * item ;
proto_tree * tree ;
2009-05-20 10:08:00 +00:00
proto_tree * next_tree = NULL ;
2007-06-24 05:28:27 +00:00
tvbuff_t * next_tvb = NULL ;
tvbuff_t * data_tvb = NULL ;
2013-07-17 21:12:24 +00:00
fragment_head * frag_msg = NULL ;
2007-06-24 05:28:27 +00:00
guint32 fragment_length ;
guint32 rtse_id = 0 ;
2007-06-27 17:57:44 +00:00
gboolean data_handled = FALSE ;
2013-11-05 18:47:26 +00:00
struct SESSION_DATA_STRUCTURE * session ;
2007-06-24 05:28:27 +00:00
conversation_t * conversation = NULL ;
2007-05-13 20:58:29 +00:00
asn1_ctx_t asn1_ctx ;
asn1_ctx_init ( & asn1_ctx , ASN1_ENC_BER , TRUE , pinfo ) ;
2005-09-04 16:22:12 +00:00
2013-12-09 22:23:44 +00:00
/* do we have application context from the acse dissector? */
if ( data = = NULL )
2013-11-05 18:47:26 +00:00
return 0 ;
2013-12-09 22:23:44 +00:00
session = ( struct SESSION_DATA_STRUCTURE * ) data ;
2005-09-04 16:22:12 +00:00
2013-12-09 22:23:44 +00:00
/* save parent_tree so subdissectors can create new top nodes */
top_tree = parent_tree ;
2013-11-05 18:47:26 +00:00
asn1_ctx . private_data = session ;
2009-08-09 06:26:46 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " RTSE " ) ;
2013-11-05 18:47:26 +00:00
col_clear ( pinfo - > cinfo , COL_INFO ) ;
2005-09-04 16:22:12 +00:00
2012-09-10 15:24:00 +00:00
if ( rtse_reassemble & &
2007-06-24 05:28:27 +00:00
( ( session - > spdu_type = = SES_DATA_TRANSFER ) | |
( session - > spdu_type = = SES_MAJOR_SYNC_POINT ) ) ) {
/* Use conversation index as fragment id */
2012-09-10 15:24:00 +00:00
conversation = find_conversation ( pinfo - > fd - > num ,
& pinfo - > src , & pinfo - > dst , pinfo - > ptype ,
2007-06-24 05:28:27 +00:00
pinfo - > srcport , pinfo - > destport , 0 ) ;
2012-09-10 15:24:00 +00:00
if ( conversation ! = NULL ) {
2007-06-24 05:28:27 +00:00
rtse_id = conversation - > index ;
2012-09-10 15:24:00 +00:00
}
2007-06-24 05:28:27 +00:00
session - > rtse_reassemble = TRUE ;
}
if ( rtse_reassemble & & session - > spdu_type = = SES_MAJOR_SYNC_POINT ) {
2013-03-22 23:59:54 +00:00
frag_msg = fragment_end_seq_next ( & rtse_reassembly_table ,
pinfo , rtse_id , NULL ) ;
2012-09-10 15:24:00 +00:00
next_tvb = process_reassembled_data ( tvb , offset , pinfo , " Reassembled RTSE " ,
2007-06-24 05:28:27 +00:00
frag_msg , & rtse_frag_items , NULL , parent_tree ) ;
}
2013-11-05 18:47:26 +00:00
item = proto_tree_add_item ( parent_tree , proto_rtse , next_tvb ? next_tvb : tvb , 0 , - 1 , ENC_NA ) ;
tree = proto_item_add_subtree ( item , ett_rtse ) ;
2007-06-24 05:28:27 +00:00
if ( rtse_reassemble & & session - > spdu_type = = SES_DATA_TRANSFER ) {
/* strip off the OCTET STRING encoding - including any CONSTRUCTED OCTET STRING */
2010-08-24 15:09:11 +00:00
dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , offset , hf_rtse_segment_data , & data_tvb ) ;
2007-06-27 17:57:44 +00:00
if ( data_tvb ) {
fragment_length = tvb_length_remaining ( data_tvb , 0 ) ;
2010-08-24 15:09:11 +00:00
proto_item_append_text ( asn1_ctx . created_item , " (%u byte%s) " , fragment_length ,
2007-06-27 17:57:44 +00:00
plurality ( fragment_length , " " , " s " ) ) ;
2013-03-22 23:59:54 +00:00
frag_msg = fragment_add_seq_next ( & rtse_reassembly_table ,
data_tvb , 0 , pinfo ,
rtse_id , NULL ,
fragment_length , TRUE ) ;
2007-06-27 17:57:44 +00:00
if ( frag_msg & & pinfo - > fd - > num ! = frag_msg - > reassembled_in ) {
/* Add a "Reassembled in" link if not reassembled in this frame */
proto_tree_add_uint ( tree , * ( rtse_frag_items . hf_reassembled_in ) ,
data_tvb , 0 , 0 , frag_msg - > reassembled_in ) ;
}
pinfo - > fragmented = TRUE ;
data_handled = TRUE ;
2007-08-13 16:41:16 +00:00
} else {
fragment_length = tvb_length_remaining ( tvb , offset ) ;
2007-06-24 05:28:27 +00:00
}
2007-08-13 16:41:16 +00:00
2013-06-14 12:44:50 +00:00
col_append_fstr ( pinfo - > cinfo , COL_INFO , " [RTSE fragment, %u byte%s] " ,
2007-08-13 16:41:16 +00:00
fragment_length , plurality ( fragment_length , " " , " s " ) ) ;
2007-06-24 05:28:27 +00:00
} else if ( rtse_reassemble & & session - > spdu_type = = SES_MAJOR_SYNC_POINT ) {
if ( next_tvb ) {
/* ROS won't do this for us */
session - > ros_op = ( ROS_OP_INVOKE | ROS_OP_ARGUMENT ) ;
2014-01-13 22:25:13 +00:00
/*offset=*/ dissect_ber_external_type ( FALSE , tree , next_tvb , 0 , & asn1_ctx , - 1 , call_rtse_external_type_callback ) ;
2014-01-27 09:55:46 +00:00
top_tree = NULL ;
/* Return other than 0 to indicate that we handled this packet */
return 1 ;
2007-06-24 05:28:27 +00:00
} else {
offset = tvb_length ( tvb ) ;
}
pinfo - > fragmented = FALSE ;
2007-06-27 17:57:44 +00:00
data_handled = TRUE ;
2012-09-10 15:24:00 +00:00
}
2007-06-27 17:57:44 +00:00
if ( ! data_handled ) {
2007-06-24 05:28:27 +00:00
while ( tvb_reported_length_remaining ( tvb , offset ) > 0 ) {
old_offset = offset ;
offset = dissect_rtse_RTSE_apdus ( TRUE , tvb , offset , & asn1_ctx , tree , - 1 ) ;
if ( offset = = old_offset ) {
2009-05-20 10:08:00 +00:00
item = proto_tree_add_text ( tree , tvb , offset , - 1 , " Unknown RTSE PDU " ) ;
2013-06-03 03:42:36 +00:00
expert_add_info ( pinfo , item , & ei_rtse_unknown_rtse_pdu ) ;
next_tree = proto_item_add_subtree ( item , ett_rtse_unknown ) ;
dissect_unknown_ber ( pinfo , tvb , offset , next_tree ) ;
2007-06-24 05:28:27 +00:00
break ;
}
2005-09-04 16:22:12 +00:00
}
}
top_tree = NULL ;
2013-11-05 18:47:26 +00:00
return tvb_length ( tvb ) ;
2005-09-04 16:22:12 +00:00
}
2007-06-24 05:28:27 +00:00
static void rtse_reassemble_init ( void )
{
2013-03-22 23:59:54 +00:00
reassembly_table_init ( & rtse_reassembly_table ,
& addresses_reassembly_table_functions ) ;
2007-06-24 05:28:27 +00:00
}
2005-09-04 16:22:12 +00:00
/*--- proto_register_rtse -------------------------------------------*/
void proto_register_rtse ( void ) {
/* List of fields */
static hf_register_info hf [ ] =
{
2007-06-24 05:28:27 +00:00
/* Fragment entries */
2010-08-24 15:09:11 +00:00
{ & hf_rtse_segment_data ,
{ " RTSE segment data " , " rtse.segment " , FT_NONE , BASE_NONE ,
NULL , 0x00 , NULL , HFILL } } ,
2007-06-24 05:28:27 +00:00
{ & hf_rtse_fragments ,
{ " RTSE fragments " , " rtse.fragments " , FT_NONE , BASE_NONE ,
2010-09-30 19:35:51 +00:00
NULL , 0x00 , NULL , HFILL } } ,
2007-06-24 05:28:27 +00:00
{ & hf_rtse_fragment ,
{ " RTSE fragment " , " rtse.fragment " , FT_FRAMENUM , BASE_NONE ,
2010-09-30 19:35:51 +00:00
NULL , 0x00 , NULL , HFILL } } ,
2007-06-24 05:28:27 +00:00
{ & hf_rtse_fragment_overlap ,
{ " RTSE fragment overlap " , " rtse.fragment.overlap " , FT_BOOLEAN ,
2010-09-30 19:35:51 +00:00
BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
2007-06-24 05:28:27 +00:00
{ & hf_rtse_fragment_overlap_conflicts ,
{ " RTSE fragment overlapping with conflicting data " ,
2010-09-30 19:35:51 +00:00
" rtse.fragment.overlap.conflicts " , FT_BOOLEAN , BASE_NONE ,
NULL , 0x0 , NULL , HFILL } } ,
2007-06-24 05:28:27 +00:00
{ & hf_rtse_fragment_multiple_tails ,
{ " RTSE has multiple tail fragments " ,
" rtse.fragment.multiple_tails " , FT_BOOLEAN , BASE_NONE ,
2010-09-30 19:35:51 +00:00
NULL , 0x0 , NULL , HFILL } } ,
2007-06-24 05:28:27 +00:00
{ & hf_rtse_fragment_too_long_fragment ,
{ " RTSE fragment too long " , " rtse.fragment.too_long_fragment " ,
2010-09-30 19:35:51 +00:00
FT_BOOLEAN , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
2007-06-24 05:28:27 +00:00
{ & hf_rtse_fragment_error ,
{ " RTSE defragmentation error " , " rtse.fragment.error " , FT_FRAMENUM ,
2010-09-30 19:35:51 +00:00
BASE_NONE , NULL , 0x00 , NULL , HFILL } } ,
2011-01-30 21:01:07 +00:00
{ & hf_rtse_fragment_count ,
{ " RTSE fragment count " , " rtse.fragment.count " , FT_UINT32 , BASE_DEC ,
NULL , 0x00 , NULL , HFILL } } ,
2007-06-24 05:28:27 +00:00
{ & hf_rtse_reassembled_in ,
{ " Reassembled RTSE in frame " , " rtse.reassembled.in " , FT_FRAMENUM , BASE_NONE ,
NULL , 0x00 , " This RTSE packet is reassembled in this frame " , HFILL } } ,
2010-02-02 16:01:52 +00:00
{ & hf_rtse_reassembled_length ,
{ " Reassembled RTSE length " , " rtse.reassembled.length " , FT_UINT32 , BASE_DEC ,
NULL , 0x00 , " The total length of the reassembled payload " , HFILL } } ,
2007-06-24 05:28:27 +00:00
2005-09-04 16:22:12 +00:00
# include "packet-rtse-hfarr.c"
} ;
/* List of subtrees */
static gint * ett [ ] = {
& ett_rtse ,
& ett_rtse_unknown ,
2007-06-24 05:28:27 +00:00
& ett_rtse_fragment ,
& ett_rtse_fragments ,
2005-09-04 16:22:12 +00:00
# include "packet-rtse-ettarr.c"
} ;
2013-06-03 03:42:36 +00:00
static ei_register_info ei [ ] = {
{ & ei_rtse_dissector_oid_not_implemented , { " rtse.dissector_oid_not_implemented " , PI_UNDECODED , PI_WARN , " RTSE: Dissector for OID not implemented " , EXPFILL } } ,
{ & ei_rtse_unknown_rtse_pdu , { " rtse.unknown_rtse_pdu " , PI_UNDECODED , PI_WARN , " Unknown RTSE PDU " , EXPFILL } } ,
} ;
expert_module_t * expert_rtse ;
2007-06-24 05:28:27 +00:00
module_t * rtse_module ;
2005-09-04 16:22:12 +00:00
/* Register protocol */
proto_rtse = proto_register_protocol ( PNAME , PSNAME , PFNAME ) ;
2013-11-05 18:47:26 +00:00
new_register_dissector ( " rtse " , dissect_rtse , proto_rtse ) ;
2005-09-04 16:22:12 +00:00
/* Register fields and subtrees */
proto_register_field_array ( proto_rtse , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2013-06-03 03:42:36 +00:00
expert_rtse = expert_register_protocol ( proto_rtse ) ;
expert_register_field_array ( expert_rtse , ei , array_length ( ei ) ) ;
2007-06-24 05:28:27 +00:00
register_init_routine ( & rtse_reassemble_init ) ;
rtse_module = prefs_register_protocol_subtree ( " OSI " , proto_rtse , NULL ) ;
prefs_register_bool_preference ( rtse_module , " reassemble " ,
" Reassemble segmented RTSE datagrams " ,
" Whether segmented RTSE datagrams should be reassembled. "
" To use this option, you must also enable "
" \" Allow subdissectors to reassemble TCP streams \" "
" in the TCP protocol settings. " , & rtse_reassemble ) ;
2005-09-04 16:22:12 +00:00
rtse_oid_dissector_table = register_dissector_table ( " rtse.oid " , " RTSE OID Dissectors " , FT_STRING , BASE_NONE ) ;
oid_table = g_hash_table_new ( g_str_hash , g_str_equal ) ;
2005-12-14 21:02:56 +00:00
2005-09-04 16:22:12 +00:00
}
/*--- proto_reg_handoff_rtse --- */
void proto_reg_handoff_rtse ( void ) {
2005-10-24 21:42:19 +00:00
2005-12-14 21:02:56 +00:00
2005-09-04 16:22:12 +00:00
}