2004-10-06 09:03:42 +00:00
/* packet-icep.c
* Routines for " The ICE Protocol " dissection
2011-02-07 18:49:29 +00:00
* Copyright 2004 _FF_
2004-10-06 09:03:42 +00:00
* Francesco Fondelli < fondelli dot francesco , tiscali dot it >
*
2006-05-21 04:49:01 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
2004-10-06 09:03:42 +00:00
* Copyright 1998 Gerald Combs
2011-02-07 18:49:29 +00:00
*
2004-10-06 09:03:42 +00:00
* This program is free software ; you can redistribute it and / or
2006-09-18 13:59:30 +00:00
* modify it under the terms of the GNU General Public License
2004-10-06 09:03:42 +00:00
* as published by the Free Software Foundation ; either version 2
2006-09-18 13:59:30 +00:00
* of the License , or ( at your option ) any later version .
2011-02-07 18:49:29 +00:00
*
2004-10-06 09:03:42 +00:00
* 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
2006-09-18 13:59:30 +00:00
* GNU General Public License for more details .
2011-02-07 18:49:29 +00:00
*
2006-09-18 13:59:30 +00:00
* You should have received a copy of the GNU General Public License
2004-10-06 09:03:42 +00:00
* along with this program ; if not , write to the Free Software
2012-06-28 23:18:38 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
2004-10-06 09:03:42 +00:00
*/
/*
TODO :
2006-05-31 00:23:01 +00:00
1 ) Dissect encoded data ( do sth like idl2wrs for CORBA ) .
2004-10-06 10:14:56 +00:00
2 ) Add conversations .
2012-06-10 08:24:18 +00:00
2004-10-06 09:03:42 +00:00
*/
/*
NOTES :
1 ) p . 586 Chapter 23.2 of " The ICE Protocol "
" Data is always encoded using little-endian byte order for numeric types. "
2004-10-06 10:01:36 +00:00
2 ) Informations about Ice can be found here : http : //www.zeroc.com
2004-10-06 09:03:42 +00:00
*/
2012-09-20 02:03:38 +00:00
# include "config.h"
2004-10-06 09:03:42 +00:00
# include <glib.h>
# include <epan/packet.h>
2012-06-10 08:24:18 +00:00
# include <epan/expert.h>
# include <epan/prefs.h>
2013-09-15 13:46:13 +00:00
# include <epan/wmem/wmem.h>
2006-03-20 10:52:53 +00:00
# include "packet-tcp.h"
2004-10-06 09:03:42 +00:00
2013-12-15 23:44:12 +00:00
void proto_register_icep ( void ) ;
void proto_reg_handoff_icep ( void ) ;
2004-10-06 09:03:42 +00:00
#if 0
# define DBG(str, args...) do {\
fprintf ( stdout , \
" [%s][%s][%d]: " , \
__FILE__ , \
__FUNCTION__ , \
__LINE__ ) ; \
fflush ( stdout ) ; \
fprintf ( stdout , str , # # args ) ; \
} while ( 0 )
# else
2004-10-06 17:06:12 +00:00
# define DBG0(format)
# define DBG1(format, arg1)
# define DBG2(format, arg1, arg2)
2004-10-06 09:03:42 +00:00
# endif /* 0/1 */
/* fixed values taken from the standard */
2005-07-09 00:35:13 +00:00
static const guint8 icep_magic [ ] = { ' I ' , ' c ' , ' e ' , ' P ' } ;
2013-10-13 19:56:52 +00:00
# define ICEP_HEADER_SIZE 14
# define ICEP_MIN_REPLY_SIZE 5
# define ICEP_MIN_PARAMS_SIZE 6
# define ICEP_MIN_COMMON_REQ_HEADER_SIZE 13
2004-10-06 09:03:42 +00:00
/* Initialize the protocol and registered fields */
static int proto_icep = - 1 ;
/* Message Header */
static int hf_icep_protocol_major = - 1 ;
static int hf_icep_protocol_minor = - 1 ;
static int hf_icep_encoding_major = - 1 ;
static int hf_icep_encoding_minor = - 1 ;
static int hf_icep_message_type = - 1 ;
static int hf_icep_compression_status = - 1 ;
static int hf_icep_message_size = - 1 ;
/* [Batch] Request Message Body */
static int hf_icep_request_id = - 1 ;
static int hf_icep_id_name = - 1 ;
static int hf_icep_id_category = - 1 ;
static int hf_icep_facet = - 1 ;
static int hf_icep_operation = - 1 ;
static int hf_icep_mode = - 1 ;
static int hf_icep_context = - 1 ;
static int hf_icep_params_size = - 1 ;
static int hf_icep_params_major = - 1 ;
static int hf_icep_params_minor = - 1 ;
2012-06-10 08:24:18 +00:00
static int hf_icep_params_encapsulated = - 1 ;
static int hf_icep_reply_data = - 1 ;
static int hf_icep_invocation_key = - 1 ;
static int hf_icep_invocation_value = - 1 ;
2004-10-06 09:03:42 +00:00
/* Reply Message Body */
static int hf_icep_reply_status = - 1 ;
/* Initialize the subtree pointers */
static gint ett_icep = - 1 ;
static gint ett_icep_msg = - 1 ;
2013-09-02 23:32:31 +00:00
static expert_field ei_icep_params_size = EI_INIT ;
static expert_field ei_icep_context_missing = EI_INIT ;
static expert_field ei_icep_reply_data = EI_INIT ;
static expert_field ei_icep_length = EI_INIT ;
static expert_field ei_icep_facet_max_one_element = EI_INIT ;
static expert_field ei_icep_string_too_long = EI_INIT ;
static expert_field ei_icep_string_malformed = EI_INIT ;
static expert_field ei_icep_message_type = EI_INIT ;
static expert_field ei_icep_mode_missing = EI_INIT ;
static expert_field ei_icep_params_encapsulated = EI_INIT ;
static expert_field ei_icep_params_missing = EI_INIT ;
static expert_field ei_icep_batch_requests = EI_INIT ;
static expert_field ei_icep_facet_missing = EI_INIT ;
static expert_field ei_icep_context_too_long = EI_INIT ;
2012-06-10 08:24:18 +00:00
/* Preferences */
2013-10-13 19:56:52 +00:00
static guint icep_max_batch_requests = 64 ;
static guint icep_max_ice_string_len = 512 ;
static guint icep_max_ice_context_pairs = 64 ;
static guint icep_tcp_port = 0 ;
static guint icep_udp_port = 0 ;
2012-06-10 08:24:18 +00:00
2004-10-06 09:03:42 +00:00
static const value_string icep_msgtype_vals [ ] = {
2013-10-13 19:56:52 +00:00
{ 0x0 , " Request " } ,
{ 0x1 , " Batch request " } ,
{ 0x2 , " Reply " } ,
{ 0x3 , " Validate connection " } ,
{ 0x4 , " Close connection " } ,
{ 0 , NULL }
2004-10-06 09:03:42 +00:00
} ;
static const value_string icep_zipstatus_vals [ ] = {
2013-10-13 19:56:52 +00:00
{ 0x0 , " Uncompressed, sender cannot accept a compressed reply " } ,
{ 0x1 , " Uncompressed, sender can accept a compressed reply " } ,
{ 0x2 , " Compressed, sender can accept a compressed reply " } ,
{ 0 , NULL }
2004-10-06 09:03:42 +00:00
} ;
static const value_string icep_replystatus_vals [ ] = {
2013-10-13 19:56:52 +00:00
{ 0x0 , " Success " } ,
{ 0x1 , " User exception " } ,
{ 0x2 , " Object does not exist " } ,
{ 0x3 , " Facet does not exist " } ,
{ 0x4 , " Operation does not exist " } ,
{ 0x5 , " Unknown Ice local exception " } ,
{ 0x6 , " Unknown Ice user exception " } ,
{ 0x7 , " Unknown exception " } ,
{ 0 , NULL }
2004-10-06 09:03:42 +00:00
} ;
static const value_string icep_mode_vals [ ] = {
2013-10-13 19:56:52 +00:00
{ 0x0 , " normal " } ,
{ 0x1 , " nonmutating " } ,
{ 0x2 , " idempotent " } ,
{ 0 , NULL }
2004-10-06 09:03:42 +00:00
} ;
2011-02-07 18:49:29 +00:00
/*
* This function dissects an " Ice string " , adds hf to " tree " and returns consumed
2004-10-06 09:03:42 +00:00
* bytes in " *consumed " , if errors " *consumed " is - 1.
*
* " *dest " is a null terminated version of the dissected Ice string .
*/
2012-06-10 08:24:18 +00:00
static void dissect_ice_string ( packet_info * pinfo , proto_tree * tree , proto_item * item , int hf_icep ,
2013-10-13 19:56:52 +00:00
tvbuff_t * tvb , guint32 offset , gint32 * consumed , char * * dest )
2004-10-06 09:03:42 +00:00
{
2013-10-13 19:56:52 +00:00
/* p. 586 chapter 23.2.1 and p. 588 chapter 23.2.5
* string = = Size + content
* string = 1 byte ( 0. .254 ) + string not null terminated
* or
* string = 1 byte ( 255 ) + 1 int ( 255. .2 ^ 32 - 1 ) + string not null terminated
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
guint32 Size = 0 ;
char * s = NULL ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = 0 ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* check for first byte */
if ( ! tvb_bytes_exist ( tvb , offset , 1 ) ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info_format ( pinfo , item , & ei_icep_string_malformed , " 1st byte of Size missing " ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (1st byte of Size missing) " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = - 1 ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* get the Size */
Size = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
( * consumed ) + + ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( Size = = 255 ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* check for next 4 bytes */
if ( ! tvb_bytes_exist ( tvb , offset , 4 ) ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info_format ( pinfo , item , & ei_icep_string_malformed , " second field of Size missing " ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (second field of Size missing) " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = - 1 ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* get second field of Size */
Size = tvb_get_letohl ( tvb , offset ) ;
offset + = 4 ;
( * consumed ) + = 4 ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
DBG1 ( " string.Size --> %d \n " , Size ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* check if the string exists */
if ( ! tvb_bytes_exist ( tvb , offset , Size ) ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info_format ( pinfo , item , & ei_icep_string_malformed , " missing or truncated string " ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (missing or truncated string) " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = - 1 ;
return ;
}
2004-10-06 09:03:42 +00:00
2013-10-13 19:56:52 +00:00
if ( Size > icep_max_ice_string_len ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info ( pinfo , item , & ei_icep_string_too_long ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (string too long) " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = - 1 ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( Size ! = 0 ) {
2014-06-17 15:30:58 +00:00
s = tvb_get_string_enc ( wmem_packet_scope ( ) , tvb , offset , Size , ENC_ASCII ) ;
2013-10-13 19:56:52 +00:00
proto_tree_add_string ( tree , hf_icep , tvb , offset , Size , s ) ;
} else {
s = wmem_strdup ( wmem_packet_scope ( ) , " (empty) " ) ;
/* display the 0x00 Size byte when click on a empty ice_string */
proto_tree_add_string ( tree , hf_icep , tvb , offset - 1 , 1 , s ) ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( dest ! = NULL )
* dest = s ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/*offset += Size;*/
( * consumed ) + = Size ;
return ;
2004-10-06 09:03:42 +00:00
}
2011-02-07 18:49:29 +00:00
/*
* This function dissects an " Ice facet " , adds hf ( s ) to " tree " and returns consumed
2004-10-06 09:03:42 +00:00
* bytes in " *consumed " , if errors " *consumed " is - 1.
*/
2012-06-10 08:24:18 +00:00
static void dissect_ice_facet ( packet_info * pinfo , proto_tree * tree , proto_item * item , int hf_icep ,
2013-10-13 19:56:52 +00:00
tvbuff_t * tvb , guint32 offset , gint32 * consumed )
2004-10-06 09:03:42 +00:00
{
2013-10-13 19:56:52 +00:00
/* p. 588, chapter 23.2.6:
* " facet " is a StringSeq , a StringSeq is a :
* sequence < string >
*
*
* sequence = = Size + SizeElements
* sequence = 1 byte ( 0. .254 ) + SizeElements
* or
* sequence = 1 byte ( 255 ) + 1 int ( 255. .2 ^ 32 - 1 ) + SizeElements
*
*
* p .613 . chapter 23.3 .2
* " facet has either zero elements (empty) or one element "
*
*
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
guint32 Size = 0 ; /* number of elements in the sequence */
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = 0 ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* check first byte */
if ( ! tvb_bytes_exist ( tvb , offset , 1 ) ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info ( pinfo , item , & ei_icep_facet_missing ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (facet field missing) " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = - 1 ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* get first byte of Size */
Size = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
( * consumed ) + + ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( Size = = 0 ) {
/* display the 0x00 Size byte when click on a empty ice_string */
proto_tree_add_string ( tree , hf_icep , tvb , offset - 1 , 1 , " (empty) " ) ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( Size = = 1 ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
gint32 consumed_facet = 0 ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
dissect_ice_string ( pinfo , tree , item , hf_icep , tvb , offset , & consumed_facet , NULL ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( consumed_facet = = - 1 ) {
( * consumed ) = - 1 ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/*offset += consumed_facet;*/
( * consumed ) + = consumed_facet ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* if here => Size > 1 => not possible */
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* display the XX Size byte when click here */
expert_add_info ( pinfo , item , & ei_icep_facet_max_one_element ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
col_append_str ( pinfo - > cinfo , COL_INFO , " (facet can be max one element) " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = - 1 ;
return ;
2004-10-06 09:03:42 +00:00
}
2011-02-07 18:49:29 +00:00
/*
* This function dissects an " Ice context " , adds hf ( s ) to " tree " and returns consumed
2004-10-06 09:03:42 +00:00
* bytes in " *consumed " , if errors " *consumed " is - 1.
*/
2013-10-13 19:56:52 +00:00
static void dissect_ice_context ( packet_info * pinfo , proto_tree * tree , proto_item * item ,
tvbuff_t * tvb , guint32 offset , gint32 * consumed )
2004-10-06 09:03:42 +00:00
{
2013-10-13 19:56:52 +00:00
/* p. 588, chapter 23.2.7 and p. 613, 23.3.2:
* " context " is a dictionary < string , string >
*
* dictionary < string , string > = = Size + SizeKeyValuePairs
* dictionary < string , string > = 1 byte ( 0. .254 ) + SizeKeyValuePairs
* or
* dictionary < string , string > = 1 byte ( 255 ) + 1 int ( 255. .2 ^ 32 - 1 ) + SizeKeyValuePairs
*
*/
guint32 Size = 0 ; /* number of key-value in the dictionary */
guint32 i = 0 ;
const char * s = NULL ;
( * consumed ) = 0 ;
/* check first byte */
if ( ! tvb_bytes_exist ( tvb , offset , 1 ) ) {
expert_add_info_format ( pinfo , item , & ei_icep_context_missing , " context missing " ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (context missing) " ) ;
( * consumed ) = - 1 ;
return ;
}
/* get first byte of Size */
Size = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
( * consumed ) + + ;
if ( Size = = 255 ) {
/* check for next 4 bytes */
if ( ! tvb_bytes_exist ( tvb , offset , 4 ) ) {
expert_add_info_format ( pinfo , item , & ei_icep_context_missing , " second field of Size missing " ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (second field of Size missing) " ) ;
( * consumed ) = - 1 ;
return ;
}
/* get second field of Size */
Size = tvb_get_letohl ( tvb , offset ) ;
offset + = 4 ;
( * consumed ) + = 4 ;
}
DBG1 ( " context.Size --> %d \n " , Size ) ;
if ( Size > icep_max_ice_context_pairs ) {
/* display the XX Size byte when click here */
expert_add_info ( pinfo , item , & ei_icep_context_too_long ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (too long context) " ) ;
( * consumed ) = - 1 ;
return ;
}
if ( Size = = 0 ) {
s = " (empty) " ;
/* display the 0x00 Size byte when click on a empty context */
proto_tree_add_string ( tree , hf_icep_context , tvb , offset - 1 , 1 , s ) ;
return ;
}
/* looping through the dictionary */
for ( i = 0 ; i < Size ; i + + ) {
/* key */
gint32 consumed_key = 0 ;
char * str_key = NULL ;
/* value */
gint32 consumed_value = 0 ;
char * str_value = NULL ;
proto_item * ti = NULL ;
DBG1 ( " looping through context dictionary, loop #%d \n " , i ) ;
ti = proto_tree_add_text ( tree , tvb , offset , - 1 , " Invocation Context " ) ;
dissect_ice_string ( pinfo , tree , ti , hf_icep_invocation_key , tvb , offset , & consumed_key , & str_key ) ;
if ( consumed_key = = - 1 ) {
( * consumed ) = - 1 ;
return ;
}
offset + = consumed_key ;
( * consumed ) + = consumed_key ;
dissect_ice_string ( pinfo , tree , ti , hf_icep_invocation_value , tvb , offset , & consumed_value , & str_value ) ;
if ( consumed_value = = - 1 ) {
( * consumed ) = - 1 ;
return ;
}
offset + = consumed_value ;
( * consumed ) + = consumed_value ;
if ( ti )
proto_item_set_len ( ti , ( consumed_key + consumed_value ) + 1 ) ;
}
2004-10-06 09:03:42 +00:00
}
2011-02-07 18:49:29 +00:00
/*
* This function dissects an " Ice params " , adds hf ( s ) to " tree " and returns consumed
2004-10-06 09:03:42 +00:00
* bytes in " *consumed " , if errors " *consumed " is - 1.
*/
2012-06-10 08:24:18 +00:00
static void dissect_ice_params ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
2013-10-13 19:56:52 +00:00
guint32 offset , gint32 * consumed )
2004-10-06 09:03:42 +00:00
{
2013-10-13 19:56:52 +00:00
/* p. 612, chapter 23.3.2 and p. 587, 23.2.2:
* " params " is an Encapsulation
*
* struct Encapsulation {
* int size ;
* byte major ;
* byte minor ;
* //(size - 6) bytes of data
* }
*
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
gint32 size = 0 ;
gint tvb_data_remained = 0 ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = 0 ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* check first 6 bytes */
if ( ! tvb_bytes_exist ( tvb , offset , ICEP_MIN_PARAMS_SIZE ) ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info ( pinfo , item , & ei_icep_params_missing ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (params missing) " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = - 1 ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* get the size */
size = tvb_get_letohl ( tvb , offset ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
DBG1 ( " params.size --> %d \n " , size ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( size < ICEP_MIN_PARAMS_SIZE ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info ( pinfo , item , & ei_icep_params_size ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (params size too small) " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = - 1 ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( tree ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
proto_tree_add_item ( tree , hf_icep_params_size , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
offset + = 4 ;
( * consumed ) + = 4 ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
proto_tree_add_item ( tree , hf_icep_params_major , tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
offset + = 1 ;
( * consumed ) + + ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
proto_tree_add_item ( tree , hf_icep_params_minor , tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
offset + = 1 ;
( * consumed ) + + ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
} else {
/* skip size, major, minor */
offset + = 6 ;
( * consumed ) + = 6 ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( size = = ICEP_MIN_PARAMS_SIZE ) /* no encapsulatd data present, it's normal */
return ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* check if I got all encapsulated data */
tvb_data_remained = tvb_reported_length_remaining ( tvb , offset ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( tvb_data_remained < ( size - ICEP_MIN_PARAMS_SIZE ) ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info_format ( pinfo , item , & ei_icep_params_encapsulated , " missing encapsulated data (%d bytes) " , size - ICEP_MIN_PARAMS_SIZE - tvb_data_remained ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
col_append_fstr ( pinfo - > cinfo , COL_INFO ,
" (missing encapsulated data (%d bytes)) " ,
size - ICEP_MIN_PARAMS_SIZE - tvb_data_remained ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) = - 1 ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* encapsulated params */
2014-04-06 14:57:33 +00:00
proto_tree_add_item ( tree , hf_icep_params_encapsulated , tvb , offset , ( size - ICEP_MIN_PARAMS_SIZE ) , ENC_NA ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * consumed ) + = ( size - ICEP_MIN_PARAMS_SIZE ) ;
2004-10-06 09:03:42 +00:00
}
2011-02-07 18:49:29 +00:00
static void dissect_icep_request_common ( tvbuff_t * tvb , guint32 offset ,
2013-10-13 19:56:52 +00:00
packet_info * pinfo , proto_tree * icep_sub_tree , proto_item * icep_sub_item , gint32 * total_consumed )
2004-10-06 09:03:42 +00:00
{
2013-10-13 19:56:52 +00:00
/* p. 613, chapter 23.3.3 and p. 612 chapter 23.3.2:
* Request and BatchRequest differ only in the first 4 bytes ( requestID )
* so them share this part
*
* Ice : : Identity id ;
* Ice : : StringSeq facet ;
* string operation ;
* byte mode ;
* Ice : : Context context ;
* Encapsulation params ;
* }
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
gint32 consumed = 0 ;
char * namestr = NULL ;
char * opstr = NULL ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
( * total_consumed ) = 0 ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* check common header (i.e. the batch request one)*/
if ( ! tvb_bytes_exist ( tvb , offset , ICEP_MIN_COMMON_REQ_HEADER_SIZE ) ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info_format ( pinfo , icep_sub_item , & ei_icep_length , " too short header " ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (too short header) " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
goto error ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* got at least 15 bytes */
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* "id" is a:
* struct Identity {
* string name ;
* string category ;
* }
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
dissect_ice_string ( pinfo , icep_sub_tree , icep_sub_item , hf_icep_id_name , tvb , offset , & consumed , & namestr ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( consumed = = - 1 )
goto error ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
offset + = consumed ; DBG1 ( " consumed --> %d \n " , consumed ) ;
( * total_consumed ) + = consumed ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
dissect_ice_string ( pinfo , icep_sub_tree , icep_sub_item , hf_icep_id_category , tvb , offset , & consumed , NULL ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( consumed = = - 1 )
goto error ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
offset + = consumed ; DBG1 ( " consumed --> %d \n " , consumed ) ;
( * total_consumed ) + = consumed ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* "facet" is a:
* sequence < string > StringSeq
*
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
dissect_ice_facet ( pinfo , icep_sub_tree , icep_sub_item , hf_icep_facet , tvb , offset , & consumed ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( consumed = = - 1 )
goto error ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
offset + = consumed ; DBG1 ( " consumed --> %d \n " , consumed ) ;
( * total_consumed ) + = consumed ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* "operation" is an ice_string
*
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
dissect_ice_string ( pinfo , icep_sub_tree , icep_sub_item , hf_icep_operation , tvb , offset , & consumed , & opstr ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( consumed = = - 1 )
goto error ;
else {
offset + = consumed ; DBG1 ( " consumed --> %d \n " , consumed ) ;
( * total_consumed ) + = consumed ;
2004-10-06 09:03:42 +00:00
2013-10-13 19:56:52 +00:00
if ( opstr & & namestr ) {
DBG2 ( " operation --> %s.%s() \n " , namestr , opstr ) ;
col_append_fstr ( pinfo - > cinfo , COL_INFO , " %s.%s() " ,
namestr , opstr ) ;
opstr = NULL ;
namestr = NULL ;
}
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* check and get mode byte */
if ( ! tvb_bytes_exist ( tvb , offset , 1 ) ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info ( pinfo , icep_sub_item , & ei_icep_mode_missing ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
col_append_str ( pinfo - > cinfo , COL_INFO , " (mode field missing) " ) ;
goto error ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
proto_tree_add_item ( icep_sub_tree , hf_icep_mode , tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
offset + + ; DBG0 ( " consumed --> 1 \n " ) ;
( * total_consumed ) + + ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* "context" is a dictionary<string, string>
*
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
dissect_ice_context ( pinfo , icep_sub_tree , icep_sub_item , tvb , offset , & consumed ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( consumed = = - 1 )
goto error ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
offset + = consumed ; DBG1 ( " consumed --> %d \n " , consumed ) ;
( * total_consumed ) + = consumed ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* "params" is a Encapsulation
*
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
dissect_ice_params ( pinfo , icep_sub_tree , icep_sub_item , tvb , offset , & consumed ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( consumed = = - 1 )
goto error ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/*offset += consumed;*/
DBG1 ( " consumed --> %d \n " , consumed ) ;
( * total_consumed ) + = consumed ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
return ;
2011-02-07 18:49:29 +00:00
2004-10-06 09:03:42 +00:00
error :
2013-10-13 19:56:52 +00:00
( * total_consumed ) = - 1 ;
2004-10-06 09:03:42 +00:00
}
2013-10-13 19:56:52 +00:00
static void dissect_icep_request ( tvbuff_t * tvb , guint32 offset ,
packet_info * pinfo , proto_tree * icep_tree , proto_item * icep_item )
2004-10-06 09:03:42 +00:00
{
2013-10-13 19:56:52 +00:00
/* p. 612, chapter 23.3.2:
*
* struct RequestData {
* int requestID ;
* Ice : : Identity id ;
* Ice : : StringSeq facet ;
* string operation ;
* byte mode ;
* Ice : : Context context ;
* Encapsulation params ;
* }
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
proto_item * ti = NULL ;
proto_tree * icep_sub_tree = NULL ;
gint32 consumed = 0 ;
guint32 reqid = 0 ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
DBG0 ( " dissect request \n " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* check for req id */
if ( ! tvb_bytes_exist ( tvb , offset , 4 ) ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info_format ( pinfo , icep_item , & ei_icep_length , " too short header " ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (too short header) " ) ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* got at least 4 bytes */
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* create display subtree for this message type */
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
reqid = tvb_get_letohl ( tvb , offset ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
ti = proto_tree_add_text ( icep_tree , tvb , offset , - 1 , " Request Message Body " ) ;
icep_sub_tree = proto_item_add_subtree ( ti , ett_icep_msg ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
proto_tree_add_item ( icep_sub_tree , hf_icep_request_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( reqid ! = 0 ) {
col_append_fstr ( pinfo - > cinfo , COL_INFO , " (%d): " , tvb_get_letohl ( tvb , offset ) ) ;
} else
col_append_str ( pinfo - > cinfo , COL_INFO , " (oneway): " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
offset + = 4 ;
DBG0 ( " consumed --> 4 \n " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
dissect_icep_request_common ( tvb , offset , pinfo , icep_sub_tree , ti , & consumed ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( consumed = = - 1 )
return ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/*offset += consumed;*/
DBG1 ( " consumed --> %d \n " , consumed ) ;
2004-10-06 09:03:42 +00:00
}
2011-02-07 18:49:29 +00:00
static void dissect_icep_batch_request ( tvbuff_t * tvb , guint32 offset ,
2013-10-13 19:56:52 +00:00
packet_info * pinfo , proto_tree * icep_tree , proto_item * icep_item )
2004-10-06 09:03:42 +00:00
{
2013-10-13 19:56:52 +00:00
/* p. 613, chapter 23.3.3
* A batch request msg is a " sequence " of batch request
* Sequence is Size + elements
*
* struct BatchRequestData {
* Ice : : Identity id ;
* Ice : : StringSeq facet ;
* string operation ;
* byte mode ;
* Ice : : Context context ;
* Encapsulation params ;
* }
*
* NOTE ! ! ! :
* The only real implementation of the Ice protocol puts a 32 bit count in front
* of a Batch Request , * not * an Ice : : Sequence ( as the standard says ) . Basically the
* same people wrote both code and standard so I ' ll follow the code .
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
proto_item * ti = NULL ;
proto_tree * icep_sub_tree = NULL ;
guint32 num_reqs = 0 ;
guint32 i = 0 ;
gint32 consumed = 0 ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
DBG0 ( " dissect batch request \n " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* check for first 4 byte */
if ( ! tvb_bytes_exist ( tvb , offset , 4 ) ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info_format ( pinfo , icep_item , & ei_icep_length , " counter of batch requests missing " ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (counter of batch requests missing) " ) ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
num_reqs = tvb_get_letohl ( tvb , offset ) ;
offset + = 4 ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
DBG1 ( " batch_requests.count --> %d \n " , num_reqs ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( num_reqs > icep_max_batch_requests ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info_format ( pinfo , icep_item , & ei_icep_batch_requests , " too many batch requests (%d) " , num_reqs ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
col_append_fstr ( pinfo - > cinfo , COL_INFO , " (too many batch requests, %d) " , num_reqs ) ;
return ;
}
2004-10-06 09:03:42 +00:00
2013-10-13 19:56:52 +00:00
if ( num_reqs = = 0 ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
proto_tree_add_text ( icep_tree , tvb , offset , - 1 ,
" empty batch requests sequence " ) ;
col_append_str ( pinfo - > cinfo , COL_INFO , " (empty batch requests sequence) " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
col_append_str ( pinfo - > cinfo , COL_INFO , " : " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/*
* process requests
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
for ( i = 0 ; i < num_reqs ; i + + ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
DBG1 ( " looping through sequence of batch requests, loop #%d \n " , i ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* create display subtree for this message type */
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
ti = proto_tree_add_text ( icep_tree , tvb , offset , - 1 ,
" Batch Request Message Body: #%d " , i ) ;
icep_sub_tree = proto_item_add_subtree ( ti , ett_icep_msg ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( i ! = 0 ) {
col_append_str ( pinfo - > cinfo , COL_INFO , " , " ) ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
dissect_icep_request_common ( tvb , offset , pinfo , icep_sub_tree , ti , & consumed ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( consumed = = - 1 )
return ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( icep_tree & & ti )
proto_item_set_len ( ti , consumed ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
offset + = consumed ;
DBG1 ( " consumed --> %d \n " , consumed ) ;
}
2004-10-06 09:03:42 +00:00
}
2013-10-13 19:56:52 +00:00
static void dissect_icep_reply ( tvbuff_t * tvb , guint32 offset ,
packet_info * pinfo , proto_tree * icep_tree , proto_item * icep_item )
2004-10-06 09:03:42 +00:00
{
2013-10-13 19:56:52 +00:00
/* p. 614, chapter 23.3.4:
*
* struct ReplyData {
* int requestId ;
* byte replyStatus ;
* [ . . . messageSize - 19 bytes . . . ]
* }
*/
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
gint32 messageSize = 0 ;
guint32 tvb_data_remained = 0 ;
guint32 reported_reply_data = 0 ;
proto_item * ti = NULL ;
proto_tree * icep_sub_tree = NULL ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
DBG0 ( " dissect reply \n " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* get at least a full reply message header */
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( ! tvb_bytes_exist ( tvb , offset , ICEP_MIN_REPLY_SIZE ) ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info_format ( pinfo , icep_item , & ei_icep_length , " too short header " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
col_append_str ( pinfo - > cinfo , COL_INFO , " (too short header) " ) ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* got 5 bytes, then data */
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* create display subtree for this message type */
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
ti = proto_tree_add_text ( icep_tree , tvb , offset , - 1 ,
" Reply Message Body " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
icep_sub_tree = proto_item_add_subtree ( ti , ett_icep_msg ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
proto_tree_add_item ( icep_sub_tree , hf_icep_request_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
col_append_fstr ( pinfo - > cinfo , COL_INFO , " (%d): " , tvb_get_letohl ( tvb , offset ) ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
offset + = 4 ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
proto_tree_add_item ( icep_sub_tree , hf_icep_reply_status , tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
col_append_fstr ( pinfo - > cinfo , COL_INFO , " %s " ,
val_to_str_const ( tvb_get_guint8 ( tvb , offset ) ,
2012-08-10 22:55:02 +00:00
icep_replystatus_vals ,
" unknown reply status " ) ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
offset + + ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
DBG1 ( " consumed --> %d \n " , 5 ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* check if I got all reply data */
2014-06-19 17:18:16 +00:00
tvb_data_remained = tvb_length_remaining ( tvb , offset ) ;
2013-10-13 19:56:52 +00:00
messageSize = tvb_get_letohl ( tvb , 10 ) ;
reported_reply_data = messageSize - ( ICEP_HEADER_SIZE + ICEP_MIN_REPLY_SIZE ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* no */
if ( tvb_data_remained < reported_reply_data ) {
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
expert_add_info_format ( pinfo , ti , & ei_icep_reply_data , " Reply Data (missing %d bytes out of %d) " , reported_reply_data - tvb_data_remained , reported_reply_data ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
col_append_fstr ( pinfo - > cinfo , COL_INFO ,
" (missing reply data, %d bytes) " ,
reported_reply_data - tvb_data_remained ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/*offset += tvb_data_remained;*/
DBG1 ( " consumed --> %d \n " , tvb_data_remained ) ;
return ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* yes (reported_reply_data can be 0) */
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
proto_tree_add_item ( icep_sub_tree , hf_icep_reply_data , tvb , offset , reported_reply_data , ENC_NA ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/*offset += reported_reply_data;*/
DBG1 ( " consumed --> %d \n " , reported_reply_data ) ;
2004-10-06 09:03:42 +00:00
}
2006-10-31 09:29:07 +00:00
static guint get_icep_pdu_len ( packet_info * pinfo _U_ , tvbuff_t * tvb , int offset )
2004-10-06 10:01:36 +00:00
{
2013-10-13 19:56:52 +00:00
return tvb_get_letohl ( tvb , offset + 10 ) ;
2004-10-06 10:01:36 +00:00
}
2013-11-09 17:46:28 +00:00
static int dissect_icep_pdu ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
2004-10-06 09:03:42 +00:00
{
2013-10-13 19:56:52 +00:00
/* p. 611, chapter 23.3.1:
*
* struct HeaderData {
* int magic ;
* byte protocolMajor ;
* byte protocolMinor ;
* byte encodingMajor ;
* byte encodingMinor ;
* byte messageType ;
* byte compressionStatus ;
* int messageSize ;
* }
*/
proto_item * ti , * msg_item = NULL ;
proto_tree * icep_tree ;
guint32 offset = 0 ;
/* Make entries in Protocol column and Info column on summary display */
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " ICEP " ) ;
col_add_str ( pinfo - > cinfo , COL_INFO ,
val_to_str ( tvb_get_guint8 ( tvb , 8 ) ,
icep_msgtype_vals ,
" Unknown Message Type: 0x%02x " ) ) ;
DBG0 ( " got an icep msg, start analysis \n " ) ;
/* create display subtree for the protocol */
ti = proto_tree_add_item ( tree , proto_icep , tvb , 0 , - 1 , ENC_NA ) ;
icep_tree = proto_item_add_subtree ( ti , ett_icep ) ;
if ( icep_tree ) {
/* add items to the subtree */
/* message header */
proto_tree_add_text ( icep_tree , tvb , offset , 4 ,
" Magic Number: 'I','c','e','P' " ) ;
offset + = 4 ;
proto_tree_add_item ( icep_tree , hf_icep_protocol_major ,
tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
offset + + ;
proto_tree_add_item ( icep_tree , hf_icep_protocol_minor ,
tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
offset + + ;
proto_tree_add_item ( icep_tree , hf_icep_encoding_major ,
tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
offset + + ;
proto_tree_add_item ( icep_tree , hf_icep_encoding_minor ,
tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
offset + + ;
msg_item = proto_tree_add_item ( icep_tree , hf_icep_message_type ,
tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
offset + + ;
proto_tree_add_item ( icep_tree , hf_icep_compression_status ,
tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
offset + + ;
proto_tree_add_item ( icep_tree , hf_icep_message_size ,
tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
offset + = 4 ;
} else {
offset + = ICEP_HEADER_SIZE ;
}
switch ( tvb_get_guint8 ( tvb , 8 ) ) {
case 0x0 :
DBG1 ( " request message body: parsing %d bytes \n " ,
2014-06-19 17:18:16 +00:00
tvb_length_remaining ( tvb , offset ) ) ;
2013-10-13 19:56:52 +00:00
dissect_icep_request ( tvb , offset , pinfo , icep_tree , ti ) ;
break ;
case 0x1 :
DBG1 ( " batch request message body: parsing %d bytes \n " ,
2014-06-19 17:18:16 +00:00
tvb_length_remaining ( tvb , offset ) ) ;
2013-10-13 19:56:52 +00:00
dissect_icep_batch_request ( tvb , offset , pinfo , icep_tree , ti ) ;
break ;
case 0x2 :
DBG1 ( " reply message body: parsing %d bytes \n " ,
2014-06-19 17:18:16 +00:00
tvb_length_remaining ( tvb , offset ) ) ;
2013-10-13 19:56:52 +00:00
dissect_icep_reply ( tvb , offset , pinfo , icep_tree , ti ) ;
break ;
case 0x3 :
case 0x4 :
/* messages already dissected */
break ;
default :
expert_add_info_format ( pinfo , msg_item , & ei_icep_message_type , " Unknown Message Type: 0x%02x " , tvb_get_guint8 ( tvb , 8 ) ) ;
break ;
}
2014-06-19 17:18:16 +00:00
return tvb_length ( tvb ) ;
2011-02-07 18:49:29 +00:00
}
2004-10-06 10:01:36 +00:00
/* entry point */
2013-11-09 17:46:28 +00:00
static gboolean dissect_icep_tcp ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data )
2004-10-06 10:01:36 +00:00
{
2013-10-13 19:56:52 +00:00
DBG0 ( " triggered \n " ) ;
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
if ( tvb_memeql ( tvb , 0 , icep_magic , 4 ) = = - 1 ) {
/* Not a ICEP packet. */
return FALSE ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
/* start dissecting */
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
tcp_dissect_pdus ( tvb , pinfo , tree , TRUE , ICEP_HEADER_SIZE ,
2013-11-09 17:46:28 +00:00
get_icep_pdu_len , dissect_icep_pdu , data ) ;
2004-10-06 10:01:36 +00:00
2013-10-13 19:56:52 +00:00
return TRUE ;
2004-10-06 09:03:42 +00:00
}
2013-11-09 17:46:28 +00:00
static gboolean dissect_icep_udp ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data )
2012-06-10 08:24:18 +00:00
{
2013-10-13 19:56:52 +00:00
DBG0 ( " triggered \n " ) ;
2012-06-10 08:24:18 +00:00
2013-10-13 19:56:52 +00:00
if ( tvb_memeql ( tvb , 0 , icep_magic , 4 ) = = - 1 ) {
/* Not a ICEP packet. */
return FALSE ;
}
2012-06-10 08:24:18 +00:00
2013-10-13 19:56:52 +00:00
/* start dissecting */
2013-11-09 17:46:28 +00:00
dissect_icep_pdu ( tvb , pinfo , tree , data ) ;
2013-10-13 19:56:52 +00:00
return TRUE ;
2012-06-10 08:24:18 +00:00
}
2004-10-06 09:03:42 +00:00
2006-05-21 04:49:01 +00:00
/* Register the protocol with Wireshark */
2004-10-06 09:03:42 +00:00
void proto_register_icep ( void )
2011-02-07 18:49:29 +00:00
{
2013-10-13 19:56:52 +00:00
module_t * icep_module ;
expert_module_t * expert_icep ;
/* Setup list of header fields */
static hf_register_info hf [ ] = {
{ & hf_icep_protocol_major ,
{
" Protocol Major " , " icep.protocol_major " ,
FT_INT8 , BASE_DEC , NULL , 0x0 ,
" The protocol major version number " , HFILL
}
} ,
{ & hf_icep_protocol_minor ,
{
" Protocol Minor " , " icep.protocol_minor " ,
FT_INT8 , BASE_DEC , NULL , 0x0 ,
" The protocol minor version number " , HFILL
}
} ,
{ & hf_icep_encoding_major ,
{
" Encoding Major " , " icep.encoding_major " ,
FT_INT8 , BASE_DEC , NULL , 0x0 ,
" The encoding major version number " , HFILL
}
} ,
{ & hf_icep_encoding_minor ,
{
" Encoding Minor " , " icep.encoding_minor " ,
FT_INT8 , BASE_DEC , NULL , 0x0 ,
" The encoding minor version number " , HFILL
}
} ,
{ & hf_icep_message_type ,
{
" Message Type " , " icep.message_type " ,
FT_INT8 , BASE_DEC , VALS ( icep_msgtype_vals ) , 0x0 ,
" The message type " , HFILL
}
} ,
{ & hf_icep_compression_status ,
{
" Compression Status " , " icep.compression_status " ,
FT_INT8 , BASE_DEC , VALS ( icep_zipstatus_vals ) , 0x0 ,
" The compression status of the message " , HFILL
}
} ,
{ & hf_icep_message_size ,
{
" Message Size " , " icep.message_status " ,
FT_INT32 , BASE_DEC , NULL , 0x0 ,
" The size of the message in bytes, including the header " ,
HFILL
}
} ,
{ & hf_icep_request_id ,
{
" Request Identifier " , " icep.request_id " ,
FT_INT32 , BASE_DEC , NULL , 0x0 ,
" The request identifier " ,
HFILL
}
} ,
{ & hf_icep_reply_status ,
{
" Reply Status " , " icep.protocol_major " ,
FT_INT8 , BASE_DEC , VALS ( icep_replystatus_vals ) , 0x0 ,
" The reply status " , HFILL
}
} ,
{ & hf_icep_id_name ,
{
" Object Identity Name " , " icep.id.name " ,
FT_STRINGZ , BASE_NONE , NULL , 0x0 ,
" The object identity name " , HFILL
}
} ,
{ & hf_icep_id_category ,
{
" Object Identity Content " , " icep.id.content " ,
FT_STRINGZ , BASE_NONE , NULL , 0x0 ,
" The object identity content " , HFILL
}
} ,
{ & hf_icep_facet ,
{
" Facet Name " , " icep.facet " ,
FT_STRINGZ , BASE_NONE , NULL , 0x0 ,
" The facet name " , HFILL
}
} ,
{ & hf_icep_operation ,
{
" Operation Name " , " icep.operation " ,
FT_STRINGZ , BASE_NONE , NULL , 0x0 ,
" The operation name " , HFILL
}
} ,
{ & hf_icep_mode ,
{
" Ice::OperationMode " , " icep.operation_mode " ,
FT_INT8 , BASE_DEC , VALS ( icep_mode_vals ) , 0x0 ,
" A byte representing Ice::OperationMode " , HFILL
}
} ,
{ & hf_icep_context ,
{
" Invocation Context " , " icep.context " ,
FT_STRINGZ , BASE_NONE , NULL , 0x0 ,
" The invocation context " , HFILL
}
} ,
{ & hf_icep_params_size ,
{
" Input Parameters Size " , " icep.params.size " ,
FT_INT32 , BASE_DEC , NULL , 0x0 ,
" The encapsulated input parameters size " ,
HFILL
}
} ,
{ & hf_icep_params_major ,
{
" Input Parameters Encoding Major " ,
" icep.params.major " ,
FT_INT8 , BASE_DEC , NULL , 0x0 ,
" The major encoding version of encapsulated parameters " ,
HFILL
}
} ,
{ & hf_icep_params_minor ,
{
" Input Parameters Encoding Minor " ,
" icep.params.minor " ,
FT_INT8 , BASE_DEC , NULL , 0x0 ,
" The minor encoding version of encapsulated parameters " ,
HFILL
}
} ,
{ & hf_icep_params_encapsulated ,
{
" Encapsulated parameters " ,
" icep.params.encapsulated " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
" Remaining encapsulated parameters " ,
HFILL
}
} ,
{ & hf_icep_reply_data ,
{
" Reported reply data " ,
" icep.params.reply_data " ,
FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL
}
} ,
{ & hf_icep_invocation_key ,
{
" Key " ,
" icep.invocation_key " ,
FT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL
}
} ,
{ & hf_icep_invocation_value ,
{
" Value " ,
" icep.invocation_value " ,
FT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL
}
} ,
} ;
/* Setup protocol subtree array */
static gint * ett [ ] = {
& ett_icep ,
& ett_icep_msg ,
} ;
static ei_register_info ei [ ] = {
{ & ei_icep_string_malformed , { " icep.string.malformed " , PI_MALFORMED , PI_ERROR , " String malformed " , EXPFILL } } ,
{ & ei_icep_string_too_long , { " icep.string.too_long " , PI_PROTOCOL , PI_WARN , " string too long " , EXPFILL } } ,
{ & ei_icep_facet_missing , { " icep.facet.missing " , PI_MALFORMED , PI_ERROR , " facet field missing " , EXPFILL } } ,
{ & ei_icep_facet_max_one_element , { " icep.facet.max_one_element " , PI_PROTOCOL , PI_WARN , " facet can be max one element " , EXPFILL } } ,
{ & ei_icep_context_missing , { " icep.context.missing " , PI_MALFORMED , PI_ERROR , " context missing " , EXPFILL } } ,
{ & ei_icep_context_too_long , { " icep.context.too_long " , PI_PROTOCOL , PI_WARN , " too long context " , EXPFILL } } ,
{ & ei_icep_params_missing , { " icep.params.missing " , PI_MALFORMED , PI_ERROR , " params missing " , EXPFILL } } ,
{ & ei_icep_params_size , { " icep.params.size.invalid " , PI_PROTOCOL , PI_WARN , " params size too small " , EXPFILL } } ,
{ & ei_icep_params_encapsulated , { " icep.params.encapsulated.missing " , PI_PROTOCOL , PI_WARN , " missing encapsulated data (%d bytes) " , EXPFILL } } ,
{ & ei_icep_length , { " icep.length_invalid " , PI_MALFORMED , PI_ERROR , " Invalid length " , EXPFILL } } ,
{ & ei_icep_mode_missing , { " icep.mode.missing " , PI_MALFORMED , PI_ERROR , " mode field missing " , EXPFILL } } ,
{ & ei_icep_batch_requests , { " icep.batch_requests.invalid " , PI_PROTOCOL , PI_WARN , " too many batch requests " , EXPFILL } } ,
{ & ei_icep_reply_data , { " icep.params.reply_data.missing " , PI_MALFORMED , PI_ERROR , " Reply Data missing " , EXPFILL } } ,
{ & ei_icep_message_type , { " icep.message_type.unknown " , PI_PROTOCOL , PI_WARN , " Unknown Message Type " , EXPFILL } } ,
} ;
/* Register the protocol name and description */
proto_icep =
proto_register_protocol ( " Internet Communications Engine Protocol " ,
" ICEP " , " icep " ) ;
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array ( proto_icep , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
expert_icep = expert_register_protocol ( proto_icep ) ;
expert_register_field_array ( expert_icep , ei , array_length ( ei ) ) ;
icep_module = prefs_register_protocol ( proto_icep , NULL ) ;
prefs_register_uint_preference ( icep_module , " tcp.port " ,
" ICEP TCP Port " ,
" ICEP TCP port " ,
10 ,
& icep_tcp_port ) ;
prefs_register_uint_preference ( icep_module , " udp.port " ,
" ICEP UDP Port " ,
" ICEP UDP port " ,
10 ,
& icep_udp_port ) ;
prefs_register_uint_preference ( icep_module , " max_batch_requests " ,
" Maximum batch requests " ,
" Maximum number of batch requests allowed " ,
10 , & icep_max_batch_requests ) ;
prefs_register_uint_preference ( icep_module , " max_ice_string_len " ,
" Maximum string length " ,
" Maximum length allowed of an ICEP string " ,
10 , & icep_max_ice_string_len ) ;
prefs_register_uint_preference ( icep_module , " max_ice_context_pairs " ,
" Maximum context pairs " ,
" Maximum number of context pairs allowed " ,
10 , & icep_max_ice_context_pairs ) ;
2004-10-06 09:03:42 +00:00
}
void proto_reg_handoff_icep ( void )
{
2013-10-13 19:56:52 +00:00
static gboolean icep_prefs_initialized = FALSE ;
static dissector_handle_t icep_tcp_handle , icep_udp_handle ;
static guint old_icep_tcp_port = 0 ;
static guint old_icep_udp_port = 0 ;
2012-06-10 08:24:18 +00:00
2013-10-13 19:56:52 +00:00
/* Register as a heuristic TCP/UDP dissector */
if ( icep_prefs_initialized = = FALSE ) {
icep_tcp_handle = new_create_dissector_handle ( dissect_icep_tcp , proto_icep ) ;
icep_udp_handle = new_create_dissector_handle ( dissect_icep_udp , proto_icep ) ;
2012-06-10 08:24:18 +00:00
2013-10-13 19:56:52 +00:00
heur_dissector_add ( " tcp " , dissect_icep_tcp , proto_icep ) ;
heur_dissector_add ( " udp " , dissect_icep_udp , proto_icep ) ;
2012-06-10 08:24:18 +00:00
2013-10-13 19:56:52 +00:00
icep_prefs_initialized = TRUE ;
}
2012-06-10 08:24:18 +00:00
2013-10-13 19:56:52 +00:00
/* Register TCP port for dissection */
if ( old_icep_tcp_port ! = 0 & & old_icep_tcp_port ! = icep_tcp_port ) {
dissector_delete_uint ( " tcp.port " , old_icep_tcp_port , icep_tcp_handle ) ;
}
2012-06-10 08:24:18 +00:00
2013-10-13 19:56:52 +00:00
if ( icep_tcp_port ! = 0 & & old_icep_tcp_port ! = icep_tcp_port ) {
dissector_add_uint ( " tcp.port " , icep_tcp_port , icep_tcp_handle ) ;
}
2012-06-10 08:24:18 +00:00
2013-10-13 19:56:52 +00:00
old_icep_tcp_port = icep_tcp_port ;
2012-06-10 08:24:18 +00:00
2013-10-13 19:56:52 +00:00
/* Register UDP port for dissection */
if ( old_icep_udp_port ! = 0 & & old_icep_udp_port ! = icep_udp_port ) {
dissector_delete_uint ( " udp.port " , old_icep_udp_port , icep_udp_handle ) ;
}
2012-06-10 08:24:18 +00:00
2013-10-13 19:56:52 +00:00
if ( icep_udp_port ! = 0 & & old_icep_udp_port ! = icep_udp_port ) {
dissector_add_uint ( " udp.port " , icep_udp_port , icep_udp_handle ) ;
}
2011-02-07 18:49:29 +00:00
2013-10-13 19:56:52 +00:00
old_icep_udp_port = icep_udp_port ;
2004-10-06 09:03:42 +00:00
}