diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | Makefile.am | 11 | ||||
-rw-r--r-- | doc/README.idl2eth | 103 | ||||
-rw-r--r-- | ethereal_be.py | 134 | ||||
-rw-r--r-- | ethereal_gen.py | 1521 | ||||
-rwxr-xr-x | idl2eth | 56 | ||||
-rw-r--r-- | packet-giop.c | 4972 | ||||
-rw-r--r-- | packet-giop.h | 572 |
8 files changed, 6814 insertions, 556 deletions
@@ -472,6 +472,7 @@ Johan Jorgensen <johan.jorgensen@axis.com> { Frank Singleton <frank.singleton@ericsson.com> { Short integer CDR support for GIOP + Support for protocols running atop GIOP } Kevin Shi <techishi@ms22.hinet.net> { diff --git a/Makefile.am b/Makefile.am index 228ccdc4ba..3345f47d63 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for Ethereal # -# $Id: Makefile.am,v 1.335 2001/06/14 09:25:22 guy Exp $ +# $Id: Makefile.am,v 1.336 2001/06/18 05:27:16 guy Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@ethereal.com> @@ -275,6 +275,7 @@ noinst_HEADERS = \ packet-fddi.h \ packet-fr.h \ packet-frame.h \ + packet-giop.h \ packet-gnutella.h \ packet-hclnfsd.h \ packet-http.h \ @@ -637,23 +638,27 @@ EXTRA_DIST = \ debian/postinst \ debian/prerm \ debian/rules \ - doc/README.developer \ doc/Makefile.in \ doc/Makefile.am \ + doc/README.developer \ + doc/README.idl2eth \ doc/README.regression \ doc/README.tvbuff \ doc/dfilter2pod.pl \ doc/editcap.pod \ - doc/text2pcap.pod \ doc/ethereal.pod.template \ doc/randpkt.txt \ doc/tethereal.pod.template \ + doc/text2pcap.pod \ editcap.c \ + ethereal_be.py \ + ethereal_gen.py \ text2pcap.c \ text2pcap.h \ text2pcap-scanner.l \ getopt.c \ getopt.h \ + idl2eth \ ieee-float.h \ image/Makefile.nmake \ image/editcap.rc.in \ diff --git a/doc/README.idl2eth b/doc/README.idl2eth new file mode 100644 index 0000000000..b3105f9d36 --- /dev/null +++ b/doc/README.idl2eth @@ -0,0 +1,103 @@ +$Id: README.idl2eth,v 1.1 2001/06/18 05:27:18 guy Exp $ + +Copyright (C) 2001 Frank Singleton <frank.singleton@ericsson.com> + + +How to use idl2eth +================== + +To use the idl2eth to generate ethereal dissectors, you +need the following. + + +1. Python must be installed + http://python.org/ + +2. omniidl from the the omniORB package must be available. + http://www.uk.research.att.com/omniORB/omniORB.html + +3 Of course you can have ethereal installed to compile the + code an tweak it if required. + +4. You need ethereal_be.py and ethereal_gen.py, part of the idl2eth + code. + +Procedure +========= + +1. To write the C code to stdout. + + idl2eth <your file.idl> + + eg: idl2eth echo.idl + + +2. To write to a file, just redirect the output. + + idl2eth echo.idl > packet-test-idl.c + + You may wish to comment out the register_giop_user_module() code + and that will leave you with heuristic dissection. + + +If you dont want to use the shell script wrapper, then try +steps 3 or 4 instead. + +3. To write the C code to stdout. + + Usage: omniidl -p ./ -b ethereal_be <your file.idl> + + eg: omniidl -p ./ -b ethereal_be echo.idl + + +4. To write to a file, just redirect the output. + + omniidl -p ./ -b ethereal_be echo.idl > packet-test-idl.c + + You may wish to comment out the register_giop_user_module() code + and that will leave you with heuristic dissection. + + +5. Copy the resulting C code to your ethereal src directory, edit the 2 make files + to include the packet-test-idl.c + + cp packet-test-idl.c /dir/where/ethereal/lives/ + edit Makefile.am + edit Makefile.nmake + +6. Run configure + + ./configure + +7. Compile the code + + make + +8. Good Luck !! + + +TODO +==== + +1. Exception code not generated (yet), but can be added manually. +2. Enums not converted to symbolic values (yet), but can be added manually. +3. Add command line options etc +4. More I am sure :-) + + +Limitations +=========== + +See TODO list inside packet-giop.c + + + +Notes +===== + +1. The "-p ./" option passed to omniidl indicates that the ethereal_be.py + and ethereal_gen.py are residing in the current directory. This may need + tweaking if you place these files somewhere else. + +Frank Singleton. + diff --git a/ethereal_be.py b/ethereal_be.py new file mode 100644 index 0000000000..6d818801a2 --- /dev/null +++ b/ethereal_be.py @@ -0,0 +1,134 @@ +# -*- python -*- +# +# $Id: ethereal_be.py,v 1.1 2001/06/18 05:27:16 guy Exp $ +# +# File : ethereal_be.py +# +# Author : Frank Singleton (frank.singleton@ericsson.com) +# +# Copyright (C) 2001 Frank Singleton, Ericsson Inc. +# +# This file is a backend to "omniidl", used to generate "Ethereal" +# dissectors from IDL descriptions. The output language generated +# is "C". It will generate code to use the GIOP/IIOP get_CDR_XXX API. +# +# +# Please see packet-giop.h in Ethereal distro for API description. +# Ethereal is available at http://www.ethereal.com/ +# +# Omniidl is part of the OmniOrb distribution, and is available at +# http://www.uk.research.att.com/omniORB/omniORB.html +# +# 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. +# +# Description: +# +# Omniidl Back-end which parses an IDL data structure provided by the frontend +# and generates packet-idl-xxx.[ch] for compiling as a dissector in +# Ethereal IP protocol anlayser. +# +# +# +# +# Strategy. +# +# Crawl all the way down all branches until I hit "Operation" nodes +# store the "operation" nodes in oplist[] +# +# Pass the obj.oplist[] (via an object ref) to the src code generator (ethereal_gen) class. +# and let it do the hard work ! +# +# + + +"""Ethereal IDL compiler back-end.""" + +from omniidl import idlast, idltype, idlvisitor, idlutil, output +import sys, string +from ethereal_gen import ethereal_gen_C + +# +# This class finds the "Operations" nodes, and hands them off +# to an instance of the source code generator class "ethereal_gen" +# + +class EtherealVisitor: + + def __init__(self, st): + self.st = st + self.oplist = [] # list of operation nodes + self.enumlist = [] # list of enum nodes + + + def visitAST(self, node): + for n in node.declarations(): + if isinstance(n, idlast.Module): + self.visitModule(n) + if isinstance(n, idlast.Interface): + self.visitInterface(n) + if isinstance(n, idlast.Operation): + self.visitOperation(n) + + + def visitModule(self, node): + for n in node.definitions(): + if isinstance(n, idlast.Module): + self.visitModule(n) + if isinstance(n, idlast.Interface): + self.visitInterface(n) + if isinstance(n, idlast.Operation): + self.visitOperation(n) + + + def visitInterface(self, node): + if node.mainFile(): + for c in node.callables(): + if isinstance(c, idlast.Operation): + self.visitOperation(c) + + # + # visitOperation + # + # populates the operations node list "oplist" + # + # + + def visitOperation(self,opnode): + self.oplist.append(opnode) # store operation node + + # + # visitExceptions + # + # Given an oplist, generate a list of unique exception + # nodes. + # + + +def run(tree, args): + + st = output.Stream(sys.stdout, 4) # set indent for stream + ev = EtherealVisitor(st) # create visitor object + + ev.visitAST(tree) # go find some operations + + # create a C generator object + # and generate some C code + + eg = ethereal_gen_C(ev.st, "TEST", "test", "Test Dissector Using GIOP API") + eg.genCode(ev.oplist) # pass them onto the C generator + + + diff --git a/ethereal_gen.py b/ethereal_gen.py new file mode 100644 index 0000000000..416b0314c6 --- /dev/null +++ b/ethereal_gen.py @@ -0,0 +1,1521 @@ +# -*- python -*- +# +# $Id: ethereal_gen.py,v 1.1 2001/06/18 05:27:16 guy Exp $ +# +# +# ethereal_gen.py +# +# Author : Frank Singleton (frank.singleton@ericsson.com) +# +# Copyright (C) 2001 Frank Singleton, Ericsson Inc. +# +# This file is a backend to "omniidl", used to generate "Ethereal" +# dissectors from IDL descriptions. The output language generated +# is "C". It will generate code to use the GIOP/IIOP get_CDR_XXX API. +# +# Please see packet-giop.h in Ethereal distro for API description. +# Ethereal is available at http://www.ethereal.com/ +# +# Omniidl is part of the OmniOrb distribution, and is available at +# http://www.uk.research.att.com/omniORB/omniORB.html +# +# 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. +# +# Description: +# +# Omniidl Back-end which parses an IDL list of "Operation" nodes +# passed from ethereal_be2.py and generates "C" code for compiling +# as a dissector in Ethereal IP protocol anlayser. +# +# +# Strategy (sneaky but ...) +# +# problem: I dont know what variables to declare until AFTER the helper functions +# have been built, so ... +# +# There are 2 passes through genHelpers, the first one is there just to +# make sure the fn_hash data struct is populated properly. +# The second pass is the real thing, generating code and declaring +# variables (from the 1st pass) properly. +# + + +"""Ethereal IDL compiler back-end.""" + +from omniidl import idlast, idltype, idlutil, output +import sys, string +import tempfile + +# +# Output class, generates "C" src code for the sub-dissector +# +# in: +# +# +# self - me +# st - output stream +# node - a reference to an Operations object. +# name - scoped name (Module::Module::Interface:: .. ::Operation +# + + + +# +# TODO -- FS +# +# 1. generate hf[] data for searchable fields (but what is searchable?) +# 2. add item instead of add_text() +# 3. sequence handling, +# 4. Exceptions +# 5. Fix arrays, and structs containing arrays. +# 6. Handle pragmas. +# 7. Exception can be common to many operations, so handle them outside the +# operation helper functions. +# 8. Automatic variable declaration. +# 9. wchar and wstring handling +# + + + + + + + +# dump decode_<operation> +# For return val and all parameters do +# find basic IDL type for each parameter +# output get_CDR_xxx +# output exception handling code +# +# Generate opereation-> helper delegation code (strcmp operation -> helper) +# + +class ethereal_gen_C: + + # + # Constructor + # + + def __init__(self, st, protocol_name, dissector_name ,description): + self.st = output.Stream(tempfile.TemporaryFile(),4) # for first pass only + self.st_save = st # where 2nd pass should go + self.protoname = protocol_name # Protocol Name (eg: ECHO) + self.dissname = dissector_name # Dissector name (eg: echo) + self.description = description # Detailed Protocol description (eg: Echo IDL Example) + self.exlist = [] # list of exceptions used in operations. + #self.curr_sname # scoped name of current opnode I am visiting, used for generating "C" var declares + self.fn_hash = {} # top level hash to contain function and a key = list of variable declarations + # ie a hash of lists + self.fn_hash_built = 0 # flag to indicate the ist pass is complete, and the fn_hash is correctly + # populated. + + + # + # genCode() + # + # Main entry point, controls sequence of + # generated code. + # + # + + def genCode(self,oplist): + + #self.st = output.Stream(,4) + self.genHelpers(oplist) # sneaky .. call it now, to populate the fn_hash + # so when I come to that function later, I have the variables to + # declare already. + self.fn_hash_built = 1 # DONE, so now I know , see genOperation() + + self.st = self.st_save + self.genHeader() # initial dissector comments + self.genGPL() # GPL license + self.genIncludes() + self.genDeclares(oplist) + self.genProtocol() + self.genRegisteredFields() + self.genOpList(oplist) + + self.genExceptionHelpers(oplist) + self.genHelpers(oplist) + + self.genMainEntryStart(oplist) + self.genDelegator(oplist) + self.genMainEntryEnd() + + self.gen_proto_register() + self.gen_proto_reg_handoff(oplist) + + #self.dumpvars() # debug + + + + # + # genHeader + # + # Generate Standard Ethereal Header Comments + # + # + + def genHeader(self): + self.st.out(self.template_Header,dissector_name=self.dissname) + #print "genHeader" + + # + # genGPL + # + # GPL licencse + # + # + + def genGPL(self): + #print "genGPL" + self.st.out(self.template_GPL) + + # + # genIncludes + # + # GPL licencse + # + # + + def genIncludes(self): + #print "genIncludes" + self.st.out(self.template_Includes) + + # + # denDeclares + # + # + + def genDeclares(self,oplist): + t=0 + #print "genDeclares" + + + + # + # genProtocol + # + # + + def genProtocol(self): + self.st.out(self.template_protocol, dissector_name=self.dissname) + self.st.out(self.template_init_boundary) + + + # + # genProtoAndRegisteredFields + # + # + + def genRegisteredFields(self): + self.st.out(self.template_registered_fields ) + + + + # + # genMainEntryStart + # + + def genMainEntryStart(self,oplist): + self.st.out(self.template_main_dissector_start, dissname=self.dissname, disprot=self.protoname) + self.st.inc_indent() + self.st.out(self.template_main_dissector_switch_msgtype_start) + self.st.out(self.template_main_dissector_switch_msgtype_start_request_reply) + self.st.inc_indent() + + + # + # genMainEntryEnd + # + + def genMainEntryEnd(self): + + self.st.out(self.template_main_dissector_switch_msgtype_end_request_reply) + self.st.dec_indent() + self.st.out(self.template_main_dissector_switch_msgtype_all_other_msgtype) + self.st.dec_indent() + #self.st.out(self.template_main_dissector_switch_msgtype_end) + self.st.out(self.template_main_dissector_end) + + + # + # genOpList + # + # in: oplist + # + # out: C code for IDL operations + # + # eg: + # + # static const char Penguin_Echo_echoShort_op = echoShort ; + # + + def genOpList(self,oplist): + self.st.out(self.template_comment_operations_start) + + for n in oplist: + sname = self.namespace(n, "_") + opname = n.identifier() + self.st.out(self.template_operations_declare, sname=sname, opname=opname) + + self.st.out(self.template_comment_operations_end) + + + + # + # genExceptionHelpers() + # + # Generate private helper functions to decode Exceptions used + # within operations + # + # in: oplist + # + + + def genExceptionHelpers(self,oplist): + exlist = self.get_exceptionList(oplist) # grab list of exception nodes + + self.st.out(self.template_exception_helpers_start) + + for ex in self.exlist: + #print "Exception = " + ex.identifier() + self.genExHelper() + + self.st.out(self.template_exception_helpers_end) + + + # + # genExhelper() + # + # Generate private helper functions to decode used exceptions + # + # in: exnode ( an exception node) + # + + def genExHelper(self,exnode): + t = 0 + + + + + # + # genHelpers() + # + # Generate private helper functions for each IDL operation. + # + # in: oplist + # + + + def genHelpers(self,oplist): + for op in oplist: + self.genOperation(op) + + + # + # genOperation() + # + # Generate private helper functions for a specificIDL operation. + # + # in: opnode + # + + def genOperation(self,opnode): + ##print "visitOperation called" + sname = self.namespace(opnode, "_") + if not self.fn_hash_built: + self.fn_hash[sname] = [] # init empty list as val for this sname key + # but on if the fn_hash is not already built + + self.curr_sname = sname # update current opnode's scoped name + opname = opnode.identifier() + + self.st.out(self.template_helper_function_comment, repoid=opnode.repoId() ) + + self.st.out(self.template_helper_function_start, sname=sname) + self.st.inc_indent() + + self.st.out(self.template_helper_function_vars_start) + self.dumpCvars(sname) + self.st.out(self.template_helper_function_vars_end ) + + + self.st.out(self.template_helper_switch_msgtype_start) + + self.st.out(self.template_helper_switch_msgtype_request_start) + self.st.inc_indent() + self.genOperationRequest(opnode) + self.st.out(self.template_helper_switch_msgtype_request_end) + self.st.dec_indent() + + self.st.out(self.template_helper_switch_msgtype_reply_start) + self.st.inc_indent() + + self.st.out(self.template_helper_switch_rep_status_start) +# self.st.inc_indent() + + + self.st.out(self.template_helper_switch_msgtype_reply_no_exception_start) + self.st.inc_indent() + self.genOperationReply(opnode) + self.st.out(self.template_helper_switch_msgtype_reply_no_exception_end) + self.st.dec_indent() + + self.st.out(self.template_helper_switch_msgtype_reply_user_exception_start) + self.st.inc_indent() + self.genOpExceptions(opnode) + self.st.out(self.template_helper_switch_msgtype_reply_user_exception_end) + self.st.dec_indent() + + self.st.out(self.template_helper_switch_msgtype_reply_default_start) + self.st.out(self.template_helper_switch_msgtype_reply_default_end) + + self.st.out(self.template_helper_switch_rep_status_end) + + self.st.dec_indent() + + self.st.out(self.template_helper_switch_msgtype_default_start) + self.st.out(self.template_helper_switch_msgtype_default_end) + + self.st.out(self.template_helper_switch_msgtype_end) + self.st.dec_indent() + + + + self.st.inc_indent() + #self.visitReturnVal(opnode) + #self.visitParameterList(opnode) + self.st.dec_indent() + + self.st.out(self.template_helper_function_end, sname=sname) + + + def visitReturnVal(self,opnode): + t = opnode + ##print "opnode.returnType().kind() = " , opnode.returnType().kind() + ##print "opnode.returnType().unalias().kind() = " , opnode.returnType().unalias().kind() + + + + def visitParameterList(self,opnode): + for n in opnode.parameters(): + self.visitParameter(n) + + def visitParameter(self,node): + #print "Identifier : " + node.identifier() + " : " + #print node.paramType().unalias().kind() + t = node + + + # + # Decode function parameters for a GIOP request message + # + # TODO check for enum + # + + def genOperationRequest(self,opnode): + #self.st.inc_indent() + for p in opnode.parameters(): + if p.is_in(): + #print "XXX parameter = " ,p + #print "XXX parameter type = " ,p.paramType() + #print "XXX parameter type kind = " ,p.paramType().kind() + + self.getCDR3(p.paramType(),p.identifier()) + + #self.st.dec_indent() + + # + # Decode function parameters for a GIOP reply message + # + # TODO check for enum + + + def genOperationReply(self,opnode): + + rt = opnode.returnType() # get return type + self.getCDR3(rt, "Operation return value") # return value + + for p in opnode.parameters(): + if p.is_out(): # out or inout + self.getCDR3(p.paramType(),p.identifier()) + + #self.st.dec_indent() + + def genOpExceptions(self,opnode): + for ex in opnode.raises(): + if ex.members(): + #print ex.members() + for m in ex.members(): + t=0 + #print m.memberType(), m.memberType().kind() + + def genDelegator(self,oplist): + for op in oplist: + opname = op.identifier() + sname = self.namespace(op, "_") + self.st.out(self.template_delegate_code, opname=opname, sname=sname) + + # + # Add a variable declaration to the hash of list + # + + def addvar(self, var): + if not ( var in self.fn_hash[self.curr_sname] ): + self.fn_hash[self.curr_sname].append(var) + + # + # Print the variable declaration from the hash of list + # + + + def dumpvars(self): + for fn in self.fn_hash.keys(): + print "FN = " + fn + for v in self.fn_hash[fn]: + print "-> " + v + # + # Print the "C" variable declaration from the hash of list + # for a given scoped operation name (eg: tux_penguin_eat) + # + + + def dumpCvars(self, sname): + for v in self.fn_hash[sname]: + self.st.out(v) + + + +## tk_null = 0 +## tk_void = 1 +## tk_short = 2 +## tk_long = 3 +## tk_ushort = 4 +## tk_ulong = 5 +## tk_float = 6 +## tk_double = 7 +## tk_boolean = 8 +## tk_char = 9 +## tk_octet = 10 +## tk_any = 11 +## tk_TypeCode = 12 +## tk_Principal = 13 +## tk_objref = 14 +## tk_struct = 15 +## tk_union = 16 +## tk_enum = 17 +## tk_string = 18 +## tk_sequence = 19 +## tk_array = 20 +## tk_alias = 21 +## tk_except = 22 +## tk_longlong = 23 +## tk_ulonglong = 24 +## tk_longdouble = 25 +## tk_wchar = 26 +## tk_wstring = 27 +## tk_fixed = 28 +## tk_value = 29 +## tk_value_box = 30 +## tk_native = 31 +## tk_abstract_interface = 32 + + + # + # getCDR() + # + # This is the main "iterator" function. It takes a node, and tries to output + # a get_CDR_XXX accessor method(s). It can call itself multiple times + # if I find nested structures etc. + # + + def getCDR3(self,type,name="fred"): + + pt = type.unalias().kind() # param CDR type + pn = name # param name + + #print "XXX kind = " , pt + + if pt == idltype.tk_ulong: + self.get_CDR_ulong(pn) + elif pt == idltype.tk_void: + self.get_CDR_void(pn) + elif pt == idltype.tk_short: + self.get_CDR_short(pn) + elif pt == idltype.tk_long: + self.get_CDR_long(pn) + elif pt == idltype.tk_ushort: + self.get_CDR_ushort(pn) + elif pt == idltype.tk_float: + self.get_CDR_float(pn) + elif pt == idltype.tk_double: + self.get_CDR_double(pn) + elif pt == idltype.tk_boolean: + self.get_CDR_boolean(pn) + elif pt == idltype.tk_char: + self.get_CDR_char(pn) + elif pt == idltype.tk_octet: + self.get_CDR_octet(pn) + elif pt == idltype.tk_any: + self.get_CDR_any(pn) + elif pt == idltype.tk_string: + self.get_CDR_string(pn) + elif pt == idltype.tk_wstring: + self.get_CDR_wstring(pn) + elif pt == idltype.tk_wchar: + self.get_CDR_wchar(pn) + elif pt == idltype.tk_enum: + #print type.decl() + self.get_CDR_enum(pn) + elif pt == idltype.tk_struct: + self.get_CDR_struct(type,pn) + elif pt == idltype.tk_TypeCode: # will I ever get here ? + self.get_CDR_TypeCode(type,pn) + elif pt == idltype.tk_sequence: + self.get_CDR_sequence(type,pn) + elif pt == idltype.tk_objref: + self.get_CDR_objref(type,pn) + else: + t=0 + print "XXXXX Unknown type XXXXX " , pt + + + # + # get_CDR_XXX methods are here .. + # + # + + + def get_CDR_ulong(self,pn): + self.st.out(self.template_get_CDR_ulong, varname=pn) + self.addvar("guint32 u_octet4;") + + def get_CDR_short(self,pn): + self.st.out(self.template_get_CDR_short, varname=pn) + self.addvar("gint16 s_octet2;") + + def get_CDR_void(self,pn): + self.st.out(self.template_get_CDR_void, varname=pn) + + def get_CDR_long(self,pn): + self.st.out(self.template_get_CDR_long, varname=pn) + self.addvar("gint32 s_octet4;") + + def get_CDR_ushort(self,pn): + self.st.out(self.template_get_CDR_ushort, varname=pn) + self.addvar("guint16 u_octet2;") + + def get_CDR_float(self,pn): + self.st.out(self.template_get_CDR_float, varname=pn) + self.addvar("gfloat my_float;") + + def get_CDR_double(self,pn): + self.st.out(self.template_get_CDR_double, varname=pn) + self.addvar("gdouble my_double;") + + def get_CDR_boolean(self,pn): + self.st.out(self.template_get_CDR_boolean, varname=pn) + self.addvar("guint8 u_octet1;") + + def get_CDR_char(self,pn): + self.st.out(self.template_get_CDR_char, varname=pn) + self.addvar("guint8 u_octet1;") + + + def get_CDR_octet(self,pn): + self.st.out(self.template_get_CDR_octet, varname=pn) + self.addvar("guint8 u_octet1;") + + def get_CDR_any(self,pn): + self.st.out(self.template_get_CDR_any, varname=pn) + + def get_CDR_enum(self,pn): + self.st.out(self.template_get_CDR_enum, varname=pn) + self.addvar("guint32 u_octet4;") + + def get_CDR_string(self,pn): + self.st.out(self.template_get_CDR_string, varname=pn) + self.addvar("guint32 u_octet4;") + self.addvar("gchar *seq;") + + def get_CDR_wstring(self,pn): + self.st.out(self.template_get_CDR_wstring, varname=pn) + self.addvar("guint32 u_octet4;") + self.addvar("gchar *seq;") + + def get_CDR_wchar(self,pn): + self.st.out(self.template_get_CDR_wchar, varname=pn) + self.addvar("gint8 s_octet1;") + self.addvar("gchar *seq;") + + def get_CDR_TypeCode(self,pn): + self.st.out(self.template_get_CDR_TypeCode, varname=pn) + self.addvar("guint32 u_octet4;") + + def get_CDR_objref(self,type,pn): + self.st.out(self.template_get_CDR_object) + + def get_CDR_sequence_len(self,pn): + self.st.out(self.template_get_CDR_sequence_length, seqname=pn) + self.addvar("guint32 u_octet4;") + + def get_CDR_struct(self,type,pn): + self.st.out(self.template_structure_start, name=type.name() ) + + # If I am a typedef struct {..}; node then find the struct node + + if isinstance(type.decl(), idlast.Declarator): + ntype = type.decl().alias().aliasType().decl() + else: + ntype = type.decl() # I am a struct node + + for m in ntype.members(): + for decl in m.declarators(): + if decl.sizes(): + t=0 # TODO - add array handling here. + + self.getCDR3(m.memberType(), type.name() + "_" + decl.identifier() ) + + self.st.out(self.template_structure_end, name=type.name()) + + + + # + # Generate code to access a sequence of a type + # + + def get_CDR_sequence(self,type, pn): + self.st.out(self.template_get_CDR_sequence_length, seqname=pn ) + self.st.out(self.template_get_CDR_sequence_loop_start, seqname=pn ) + self.addvar("guint32 u_octet4_loop_" + pn + ";" ) + self.addvar("guint32 i_" + pn + ";") + + self.st.inc_indent() + self.getCDR3(type.unalias().seqType() ) # and start all over with the type + self.st.dec_indent() + + self.st.out(self.template_get_CDR_sequence_loop_end) + self.addvar("guint32 u_octet4_loop_" + pn + ";" ) + + + # + # get_ret_in_inout + # + # in - opnode + # + # out - list of [operation return ] + # + # + + def get_ret_in_inout(self,opnode): + t=0 + #print "Unused" + + # + # namespace() + # + # in - op node + # + # out - scoped operation name, using sep character instead of "::" + # + # eg: Penguin::Echo::echoWString => Penguin_Echo_echoWString if sep = "_" + # + # + + def namespace(self,node,sep): + sname = string.replace(idlutil.ccolonName(node.scopedName()), '::', sep) + return sname + + + def param_decode(self,node): + t=0 + #print "Identifier : " + node.identifier() + + + # + # generate register_giop_user_module code, and register only + # unique interfaces that contain operations. Also output + # a heuristic register in case we want to use that. + # + # TODO - make this a command line option + # + # -e explicit + # -h heuristic + # + + + + def gen_proto_reg_handoff(self, oplist): + + self.st.out(self.template_proto_reg_handoff_start, dissector_name=self.dissname) + self.st.inc_indent() + + for iname in self.get_intlist(oplist): + self.st.out(self.template_proto_reg_handoff_body, dissector_name=self.dissname, protocol_name=self.protoname, interface=iname ) + + self.st.out(self.template_proto_reg_handoff_heuristic, dissector_name=self.dissname, protocol_name=self.protoname) + self.st.dec_indent() + + self.st.out(self.template_proto_reg_handoff_end) + + + + # + # generate proto_register_<protoname> code, + # + + + def gen_proto_register(self): + self.st.out(self.template_proto_register, description=self.description, protocol_name=self.protoname, dissector_name=self.dissname) + + + + + + + + # + # provide variable declarations for private helper functions. + # + # eg: u_octet32, s_octet8 etc.. + # + # + # + + def helper_fn_vars(self,node): + t=0 + #print "helper_fn_vars" + + + + # + # in - oplist[] + # + # out - a list of unique interface names. This will be used in + # register_giop_user_module(dissect_giop_auto, "TEST IDL", "Penguin/Echo" ); so the operation + # name must be removed from the scope. And we also only want unique interfaces. + # + + def get_intlist(self,oplist): + int_hash = {} # holds a hash of unique interfaces + for op in oplist: + sc = op.scopedName() # eg: penguin,tux,bite + sc1 = sc[:-1] # drop last entry + sn = idlutil.slashName(sc1) # penguin/tux + if not int_hash.has_key(sn): + int_hash[sn] = 0; # dummy val, but at least key is unique + + return int_hash.keys() + + + + # + # in - oplist[] + # + # out - a list of exception nodes (unique). This will be used in + # to generate dissect_exception_XXX functions. + # + + + + def get_exceptionList(self,oplist): + ex_hash = {} # holds a hash of unique exceptions. + for op in oplist: + for ex in op.raises(): + if not ex_hash.has_key(ex.identifier()): + ex_hash[ex.identifier()] = 0; # dummy val, but at least key is unique + #print "Exception = " + ex.identifier() + return ex_hash.keys() + + + + + + + # + # Templates for C code + # + + + + template_comment_operations_start = """\ +/* + * IDL Operations Start + */ + + """ + + + template_operations_declare = """static const char @sname@_op[] = \"@opname@\" ;""" + + + template_comment_operations_end = """ +/* + * IDL Operations End + */ + +""" + + template_helper_function_comment = """\ + +/* + * @repoid@ + */ + +""" + + template_helper_function_vars_start = """ +/* Operation specific Variable declarations Begin */ +""" + + template_helper_function_vars_end = """ +/* Operation specific Variable declarations End */ +""" + + + + template_helper_function_start = """\ +static void decode_@sname@(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, MessageHeader *header, gchar *operation) { + + gboolean stream_is_big_endian; /* big endianess */ +""" + + template_helper_function_end = """\ +} +""" + + # + # proto_reg_handoff() templates + # + + + template_proto_reg_handoff_start = """ +/* register me as handler for these interfaces */ + +void proto_register_handoff_@dissector_name@(void) { + +""" + + template_proto_reg_handoff_body = """ +#if 0 + +/* Register for Explicit Dissection */ + +register_giop_user_module(dissect_@dissector_name@, \"@protocol_name@\", \"@interface@\" ); /* explicit dissector */ + +#endif + +""" + + template_proto_reg_handoff_heuristic = """ + +/* Register for Heuristic Dissection */ + +register_giop_user(dissect_@dissector_name@, \"@protocol_name@\" ); /* heuristic dissector */ + +""" + + template_proto_reg_handoff_end = """ +} +""" + + + # + # Initialize the protocol + # + + template_protocol = """ +/* Initialise the protocol and subtree pointers */ + +static int proto_@dissector_name@ = -1; + +static gint ett_@dissector_name@ = -1; + +""" + + + + # + # Initialize the boundary Alignment + # + + template_init_boundary = """ +/* Initialise the initial Alignment */ + +static guint32 boundary = GIOP_HEADER_SIZE; /* initial value */ + +""" + + + + + + # + # Initialize the Registered fields + # + + template_registered_fields = """ + +/* Initialise the Registered fields */ + +/* TODO - Use registered fields */ + +""" + + + + + # + # proto_register_<dissector name>(void) templates + # + + + template_proto_register = """ + +/* Register the protocol with Ethereal */ + +void proto_register_@dissector_name@(void) { + + /* setup list of header fields */ + + static hf_register_info hf[] = { + + /* no fields yet */ + + }; + + /* setup protocol subtree array */ + + static gint *ett[] = { + &ett_@dissector_name@, + }; + + /* Register the protocol name and description */ + + proto_@dissector_name@ = proto_register_protocol(\"@description@\" , \"@protocol_name@\", \"@dissector_name@\" ); + + proto_register_field_array(proto_@dissector_name@, hf, array_length(hf)); + proto_register_subtree_array(ett,array_length(ett)); + +} + + +""" + + # + # template for delegation code + # + + template_delegate_code = """\ +if (!strcmp(operation, @sname@_op )) { + decode_@sname@(tvb, pinfo, tree, offset, header, operation); + return TRUE; +} +""" + + # + # Templates for the helper functions + # + # + # + + + template_helper_switch_msgtype_start = """\ + +stream_is_big_endian = is_big_endian(header); + +switch(header->message_type) { +""" + + template_helper_switch_msgtype_default_start = """\ +default: + + /* Unknown GIOP Exception */ + + g_warning("Unknown GIOP Message"); + +""" + template_helper_switch_msgtype_default_end = """\ +break; +""" + + + + template_helper_switch_msgtype_end = """\ + +} /* switch(header->message_type) */ +""" + + template_helper_switch_msgtype_request_start = """\ +case Request: +""" + + template_helper_switch_msgtype_request_end = """\ +break; +""" + + template_helper_switch_msgtype_reply_start = """\ +case Reply: +""" + + template_helper_switch_msgtype_reply_no_exception_start = """\ +case NO_EXCEPTION: +""" + + template_helper_switch_msgtype_reply_no_exception_end = """\ +break; +""" + + + template_helper_switch_msgtype_reply_user_exception_start = """\ +case USER_EXCEPTION: +""" + + template_helper_switch_msgtype_reply_user_exception_end = """\ +break; +""" + + template_helper_switch_msgtype_reply_default_start = """\ +default: + + /* Unknown Exception */ + + g_warning("Unknown Exception "); + + +""" + + template_helper_switch_msgtype_reply_default_end = """\ + break; +""" + + + template_helper_switch_msgtype_reply_end = """\ +break; +""" + + template_helper_switch_msgtype_default_start = """\ +default: + + /* Unknown GIOP Message */ + + g_warning("Unknown GIOP Message"); + +""" + + template_helper_switch_msgtype_default_end = """\ + break; +""" + + + + template_helper_switch_rep_status_start = """\ +switch(header->rep_status) { +""" + + template_helper_switch_rep_status_default_start = """\ +default: + + /* Unknown Reply Status */ + + g_warning("Unknown Reply Status"); + +""" + + template_helper_switch_rep_status_default_end = """\ + break; +""" + + template_helper_switch_rep_status_end = """\ + +} /* switch(header->message_type) */ + +break; +""" + + + + + + # + # Templates for get_CDR_xxx accessors + # + + template_get_CDR_ulong = """\ +u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian, boundary); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-4,4,"@varname@ = %u",u_octet4); +} +""" + + template_get_CDR_short = """\ +s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian, boundary); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-2,2,"@varname@ = %i",s_octet2); +} +""" + + template_get_CDR_void = """\ + +/* Function returns void */ + +""" + + template_get_CDR_long = """\ +s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian, boundary); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-4,4,"@varname@ = %i",s_octet4); +} +""" + + template_get_CDR_ushort = """\ +u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian, boundary); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-2,2,"@varname@ = %u",u_octet2); +} +""" + template_get_CDR_float = """\ +my_float = get_CDR_float(tvb,offset,stream_is_big_endian, boundary); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-4,4,"@varname@ = %.6e",my_float); +} +""" + + template_get_CDR_double = """\ +my_double = get_CDR_double(tvb,offset,stream_is_big_endian, boundary); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-8,8,"@varname@ = %.15e",my_double); +} +""" + + template_get_CDR_boolean = """\ +u_octet1 = get_CDR_boolean(tvb,offset); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-1,1,"@varname@ = %u",u_octet1); +} +""" + + template_get_CDR_char = """\ +u_octet1 = get_CDR_char(tvb,offset); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-1,1,"@varname@ = %u",u_octet1); +} +""" + + template_get_CDR_octet = """\ +u_octet1 = get_CDR_octet(tvb,offset); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-1,1,"@varname@ = %u",u_octet1); +} +""" + + template_get_CDR_any = """\ +get_CDR_any(tvb,tree,offset,stream_is_big_endian, boundary, header); + +""" + + template_get_CDR_enum = """\ + +/* TODO - translate Enum val into symbolic value */ + +u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian, boundary); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-4,4,"Enum value = %u ",u_octet4); +} +""" + + template_get_CDR_string = """\ +u_octet4 = get_CDR_string(tvb, &seq, offset, stream_is_big_endian, boundary); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-4-u_octet4,4,"length = %u",u_octet4); + if (u_octet4 > 0) + proto_tree_add_text(tree,tvb,*offset-u_octet4,u_octet4,"@varname@ = %s",seq); + +} + +g_free(seq); /* free buffer */ +seq = NULL; +""" + + + template_get_CDR_wstring = """\ +u_octet4 = get_CDR_wstring(tvb, &seq, offset, stream_is_big_endian, boundary, header); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-4-u_octet4,4,"length = %u",u_octet4); + if (u_octet4 > 0) + proto_tree_add_text(tree,tvb,*offset-u_octet4,u_octet4,"@varname@ = %s",seq); + +} + +g_free(seq); /* free buffer */ +seq = NULL; +""" + + + template_get_CDR_wchar = """\ +s_octet1 = get_CDR_wchar(tvb, &seq, offset, header); +if (tree) { + if (s_octet1 > 0) + proto_tree_add_text(tree,tvb,*offset-1-s_octet1,1,"length = %u",s_octet1); + + if (s_octet1 < 0) + s_octet1 = -s_octet1; + + if (s_octet1 > 0) + proto_tree_add_text(tree,tvb,*offset-s_octet1,s_octet1,"@varname@ = %s",seq); + +} + +g_free(seq); /* free buffer */ +seq = NULL; +""" + + + + + template_get_CDR_TypeCode = """\ +u_octet4 = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header); + +""" + + template_get_CDR_object = """\ +get_CDR_object(tvb, pinfo, tree, offset, stream_is_big_endian, boundary); + +""" + + + template_get_CDR_sequence_length = """\ +u_octet4_loop_@seqname@ = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary); +if (tree) { + proto_tree_add_text(tree,tvb,*offset-4, 4 ,"Seq length of @seqname@ = %u",u_octet4_loop_@seqname@); +} +""" + + template_get_CDR_sequence_loop_start = """\ +for (i_@seqname@=0; i_@seqname@< u_octet4_loop_@seqname@; i_@seqname@++) { +""" + template_get_CDR_sequence_loop_end = """\ +} +""" + + + template_structure_start = """\ +/* Begin struct \"@name@\" */ +""" + + + template_structure_end = """\ +/* End struct \"@name@\" */ +""" + + + + +# +# Program Header Template +# + + template_Header = """\ +/* + * packet-@dissector_name@-idl.c + * Routines for IDL dissection + * + * Autogenerated from ethereal_be.py + * Copyright 2001 Frank Singleton <frank.singleton@@ericsson.com> + */ + +""" + +# +# GPL Template +# + + + template_GPL = """\ +/* + * 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. + * + */ +""" + +# +# Includes template +# + + template_Includes = """\ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif + +#ifdef NEED_SNPRINTF_H +# ifdef HAVE_STDARG_H +# include <stdarg.h> +# else +# include <varargs.h> +# endif +# include "snprintf.h" +#endif + +#include <string.h> +#include <glib.h> +#include "packet.h" +#include "proto.h" +#include "packet-giop.h" + +""" + + +# +# Main dissector entry templates +# + + template_main_dissector_start = """\ +gboolean dissect_@dissname@(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset, MessageHeader *header, gchar *operation, gchar *idlname) { + + proto_item *ti = NULL; + proto_tree *tree = NULL; /* init later, inside if(tree) */ + + gboolean be; /* big endianess */ + guint32 offset_saved = (*offset); /* save in case we must back out */ + + pinfo->current_proto = \"@disprot@\"; + + if (check_col(pinfo->fd, COL_PROTOCOL)) + col_add_str(pinfo->fd, COL_PROTOCOL, \"@disprot@\"); + + if (ptree) { + ti = proto_tree_add_item(ptree, proto_@dissname@, tvb, *offset, tvb_length(tvb) - *offset, FALSE); + tree = proto_item_add_subtree(ti, ett_@dissname@); + } + + + be = is_big_endian(header); /* get endianess - TODO use passed in stream_is_big_endian instead ? */ + + +""" + + + + + template_main_dissector_switch_msgtype_start = """\ +switch(header->message_type) { +""" + + template_main_dissector_switch_msgtype_start_request_reply = """\ +case Request: +case Reply: + +""" + + template_main_dissector_switch_msgtype_end_request_reply = """\ + +break; +""" + + + template_main_dissector_switch_msgtype_end = """\ + + +/* + * We failed to match ANY operations, so perhaps this is not for us ! + */ + +(*offset) = offset_saved; /* be nice */ + +return FALSE; + + +""" + + + + + template_main_dissector_switch_msgtype_all_other_msgtype = """\ +case CancelRequest: +case LocateRequest: +case LocateReply: +case CloseConnection: +case MessageError: +case Fragment: + return FALSE; /* not handled yet */ + +default: + return FALSE; /* not handled yet */ + +} /* switch */ + +""" + + + template_main_dissector_switch_msgtype_end = """\ + + return TRUE; + +} /* switch */ + +""" + + template_main_dissector_end = """\ + + return FALSE; + +} /* End of main dissector */ + +""" + + + + + template_exception_helpers_start = """\ +/* Begin Exception Helper Functions */ + +""" + + template_exception_helpers_end = """\ + +/* End Exception Helper Functions */ + +""" + + + + + diff --git a/idl2eth b/idl2eth new file mode 100755 index 0000000000..d28c63ac1b --- /dev/null +++ b/idl2eth @@ -0,0 +1,56 @@ +#!/bin/sh +# +# $Id: idl2eth,v 1.1 2001/06/18 05:27:16 guy Exp $ +# +# File : idl2eth +# +# Author : Frank Singleton (frank.singleton@ericsson.com) +# +# Copyright (C) 2001 Frank Singleton, Ericsson Inc. +# +# This file is a simple shell script wrapper for the IDL to +# Ethereal dissector code. +# +# ie: ethereal_be.py and ethereal_gen.py +# +# This file is used to generate "Ethereal" dissectors from IDL descriptions. +# The output language generated is "C". It will generate code to use the +# GIOP/IIOP get_CDR_XXX API. +# +# Please see packet-giop.h in Ethereal distro for API description. +# Ethereal is available at http://www.ethereal.com/ +# +# Omniidl is part of the OmniOrb distribution, and is available at +# http://www.uk.research.att.com/omniORB/omniORB.html +# +# 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. +# + + +if [ $# -lt 1 ] + # Must at least supply an IDL file +then + echo "Error, no IDL file specified." + echo "Usage: idl2eth idl_file_name" + exit 1 +fi + + +omniidl -p ./ -b ethereal_be $1 + + + + diff --git a/packet-giop.c b/packet-giop.c index 20ac19ed8f..a9031be97b 100644 --- a/packet-giop.c +++ b/packet-giop.c @@ -1,15 +1,19 @@ /* packet-giop.c * Routines for CORBA GIOP/IIOP packet disassembly * + * Initial Code by, * Laurent Deniel <deniel@worldnet.fr> * Craig Rodrigues <rodrigc@mediaone.net> + * + * GIOP API extensions by, + * Frank Singleton <frank.singleton@ericsson.com> + * Trevor Shepherd <eustrsd@am1.ericsson.se> * - * $Id: packet-giop.c,v 1.34 2001/06/18 02:17:46 guy Exp $ + * $Id: packet-giop.c,v 1.35 2001/06/18 05:27:16 guy Exp $ * * Ethereal - Network traffic analyzer - * By Gerald Combs <gerald@zing.org> + * By Gerald Combs <gerald@ethereal.com> * 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 @@ -28,6 +32,254 @@ * */ + +/* + * TODO: -- FS + * 1. heuristic giop dissector table [started] + * 2. GUI options, see 20 + * 3. Remove unneccessary reply_status in heuristic dissector calls (now + * part of MessageHeader) [done] + * 4. get_CDR_xxx should be passed an alignment offset value + * rather than GIOP_HEADER_SIZE, as alignment can also change in a + * octet stream when eg: encapsulation is used [done] + * 5. GIOP users should eventually get there own tvbuff, and + * not rely on the GIOP tvbuff, more robust + * 6. get_CDR_string,wchar,wstring etc should handle different + * GIOP versions [started] + * 7. Fix situation where req_id is not unique in a logfile [done, use FN/MFN, needs improving.] + * + * 8. Keep request_1_2 in step with request_1_1 [started] + * 9. Explicit module name dissection [done] + * 10. Decode IOR and put in a useful struct [IOR decode started] + * 11. Fix encapsulation of IOR etc and boundary [done] + * 12. handle get_CDR_typeCode() [started] + * 13. Handle different IOR profiles + * 14. Change printable_string to RETURN a new string, not to modify the old. + * or, new function, make_printable_string [done, make_printable_string] + * + * 15. Handle "TCKind", and forget about eg: enum translation to symbolic values + * otherwise need knowledge of sub dissectors data - YUK [done] + * 16. Handle multiple RepoId representations, besides IDL:Echo:1.0 (see 13.) + * 17. Pass subset of RepoID to explicit dissector. + * eg : If IDL:Mod1/Mod2/Int3:1.0 then pass "Mod1/Mode2/Int3" to sub dissector[done] + * 18. Better hashing algorithms + * 19. Handle hash collision properly . + * 20. Allow users to paste a stringified IOR into the GUI, and tie it + * to a sub_dissector. + * 21. Add complete_request_packet_list and complete_reply_packet_hash.[done] + * 22. Handle case where users click in any order, AND try and match + * REPLY msg to the correct REQUEST msg when we have a request_id collision.[done] + * 23. Clean up memory management for all those g_malloc's etc + * 24. register_giop_user_module could return a key for every distinct Module/Interface + * the sub_dissector uses. So, instead of strcmp()'s when handling the + * namespace of an operation, we could have a lookup table instead. + * 25. A few typedefs in the right place. + * 26 Improve handling of gchar * and use const gchar * where possible. + * 27. Read/write IOR etc to/from file, allows objkey hash to be built from + * external data [read done, write incomplete] + * 28. Call sub dissector only if tvb_offset_exists(). [Done, this is checked + * inside try_explicit_giop_dissector() ] + * + * 29. Make add/delete routine for objkey hash as it may be useful when say reading + * stringified IOR's from a file to add them to our hash. ie: There are other ways + * to populate our object key hash besides REPLY's to RESOLVE(request) [done] + * + * 30. Add routine to encode/decode stringified IOR's [decode done] + * 31. Add routine to read IOR's from file [done] + * 32. TypeCode -none-, needs decoding. + * 33. Complete dissect_data_for_typecode. + * 34. For complex TypeCodes need to check final offset against original offset + sequence length. + * 35. Update REQUEST/REPLY 1_2 according to IDL (eg; ServiceContextList etc). + * 36. Adding decode_ServiceContextList, incomplete. + * 37. Helper functions should not ALWAYS rely on header to find current endianess. It should + * be passed from user, eg Use stream_is_big_endian. [started] + * 38. Remove unwanted/unused function parameters, see decode_IOR [started] + * 40. Add sequence <IOP::TaggedComponent> components to IIOP IOR profile. Perhaps + * decode_IOP_TaggedComponents as a helper function. [done - NOT helper] + * + * 41. Make important field searchable from Message header. ie: Remove add_text_ + * 42. Use sub-tree for decode_ServiceContextList, looks better. + * 43. dissect_reply_body, no exception dissector calls + * - call subdiss directly, as we already have handle. + * - add repoid to heuristic call also. + * + * 44. typedef using xxx_t in .h file. + * 45. Subdissectors should not be passed MessageHeader to find endianness and + * version, they should be passed directly ? + * 46. get_CDR_wchar and wstring need wide chars decoded (just dumped in + * any readable form at present, not handled well at all, suggestions welcome -- FS + * 47. Change ...add_text to ...add_xxx (ie use hf fields). + * + * 48. BUG - file load with a GIOP filter set, causes the FN/MFN data struct to be + * not initiated properly. Hit "Reload" as a workaround, til I fix this -- FS + * + */ + + + +/* + * Intended Decode strategy: + * ========================= + * + * Initial Pass + * ------------ + * REQUEST: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t + * and populate complete_request_packet_hash + * + * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t + * + * User Clicks + * ----------- + * + * REQUEST: FN -> giop_sub_handle_t directly (via complete_request_packet_hash) + * + * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t + * (via complete_request_packet_hash + * + * + * Limitations. + * ============ + * + * 1. Request_ID's are unique only per connection. + * + * 2. You must be monitoring the network when the client does + * a REQUEST(resolve), otherwise I have no knowledge of the + * association between object_key and REPOID. I could talk to + * a Nameserver, but then I would start "generating" packets. + * This is probably not a good thing for a protocol analyser. + * Also, how could I decode logfiles offline. + * + * TODO -- Read stringified IORs from an input file.[done] + * + * 3. User clicks (REQUEST) is currently handle the same as + * the initial pass handling. + * + * ie: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t + */ + + +/* + * Important Data Structures: + * + * giop_module_hash + * ---------------- + * + * This is a hash table that maps IDL Module/Interface Names (Key) + * to sub_dissector handles, giop_sub_handle_t. It is populated + * by subdissectors, via register_giop_user_module(). This + * table is used when we have a REPOID, and explicitly wish to + * call the subdissector that has registered responsibility for + * that IDL module/interface. + * + * + * giop_sub_list + * ------------- + * + * This singly linked list is used to hold entries for + * heuristic based subdissectors. It is populated by sub_dissectors + * wishing to be called via heuristic mechanisms. They do this + * via the register_giop_user() function. + * + * + * giop_objkey_hash + * ---------------- + * + * This hash table maps object_key's (key) onto REPOID's (val). + * Once a client has REQUEST(resolve) an object , it knows about + * an object (interface) via its object_key (see IOR). So in order to follow + * packets that contain an object_key only, and to be able to forward it + * to the correct explicit subdissector, we need this table. + * + * So, I listen in on REQUEST(resolve) messages between client and + * Nameserver, and store the respones (REPLY/Objkey,Repo_ID) here. + * + * Also, stringified IOR's can be read from a file "IOR.txt" and used + * to populate this hash also. + * + * + * Other Data structures + * ======================= + * + * These structures have been added to minimise the possibility + * of incorrectly interpreted packets when people click all + * over the place, in no particular order, when the request_id's are + * not unique as captured. If all request_is'd are unique, as captured, then + * we would not have to deal with this problem. + * + * + * When the logfile or packets are initially being processed, I will + * build 2 structures. The intent is to be able to map a REPLY message + * back to the most recent REQUEST message with the same Request_ID + * (TODO and matching port and IP address ??) + * + * Abbrevs: + * -------- + * + * FN - Frame Number + * MFN - Matching Frame Number + * + * + * complete_request_packet_list + * ---------------------------- + * + * This is a list that contains ALL the FN's that are REQUEST's, along with + * operation,request_id and giop_sub_handle_t + * + * complete_reply_packet_hash + * -------------------------- + * + * This is a hash table. It is populated with FN (key) and MFN (val). + * This allows me to handle the case, where if you click on any REPLY + * message, I can lookup the matching request. This can improve + * the match rate between REQUEST and REPLY when people click in + * any old fashion, but is NOT foolproof. + * + * The algorithm I use to populate this hash during initial pass, + * is as follows. + * + * If packet is a REPLY, note the reqid, and then traverse backwards + * through the complete_request_packet_list from its tail, looking + * for a FN that has the same Request_id. Once found, take the found FN + * from complete_reply_packet_hash, and insert it into the MFN field + * of the complete_reply_packet_hash. + * + * + * See TODO for improvements to above algorithm. + * + * So now when people click on a REQUEST packet, I can call lookup the + * giop_sub_handle_t directly from complete_request_packet_list. + * + * And, when they click on a REPLY, I grab the MFN of this FN from + * complete_reply_packet_hash, then look that up in the complete_request_packet_list + * and call the sub_dissector directly. + * + * So, how do I differentiate between the initial processing of incoming + * packets, and a user clickin on one ? Good question. + * + * I leverage the pinfo_fd->flags.visited on a per frame + * basis. + * + * To quote from the ever helpful development list + * + * " When a capture file is initially loaded, all "visited" flags + * are 0. Ethereal then makes the first pass through file, + * sequentially dissecting each packet. After the packet is + * dissected the first time, "visited" is 1. (See the end of + * dissect_packet() in epan/packet.c; that's the code that + * sets "visited" to 1). + + * By the time a user clicks on a packet, "visited" will already + * be 1 because Ethereal will have already done its first pass + * through the packets. + + * Reload acts just like a normal Close/Open, except that it + * doesn't need to ask for a filename. So yes, the reload button + * clears the flags and re-dissects the file, just as if the file + * had been "opened". " + * + */ + + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -37,13 +289,175 @@ #endif #include <string.h> +#include <stdio.h> +#include <errno.h> #include <ctype.h> #include <glib.h> +#include <math.h> +#include "strerror.h" + #include "packet.h" +#include "packet-giop.h" + +/* + * This affects how we handle context_data inside ServiceContext structs. + * According to CORBA 2.4.2, Context data is encapsulated in octet sequences, + * but so far I haven't seen the that on the wire. But, maybe its me -- FS + * + */ + +#define CONTEXT_DATA_IS_ENCAPSULATED 0 + + +/* + * Set to 1 for DEBUG output + */ + +#define DEBUG 0 + +/* + * To allow calling (or not) of subdissectors, for testing buggy stuff. + */ + +#define DEBUG_CALL_SUB_DISSECTORS 1 + + +/* + * ------------------------------------------------------------------------------------------+ + * Private Helper function Declarations + * ------------------------------------------------------------------------------------------+ + */ + + +static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + guint32 boundary, gboolean new_endianess, gchar *repobuf, + gboolean store_flag); + +static void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + gboolean stream_is_be, guint32 boundary); + +static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf); + +static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + guint32 boundary, gboolean stream_is_big_endian ); + +static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, + guint32 boundary); + +static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header); + +static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header); + +static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header ); + +static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header); + +static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header); + +static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header); + +static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header); + +static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header); + +static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header); + +static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header); + +static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header); + +static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header); + + +static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ); + +static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header, guint32 data_type ); + + + + +/* + * ------------------------------------------------------------------------------------------+ + * Data/Variables/Structs + * ------------------------------------------------------------------------------------------+ + */ + static int proto_giop = -1; static int hf_giop_message_type = -1; static int hf_giop_message_size = -1; +static int hf_giop_repoid = -1; +static int hf_giop_string_length = -1; +static int hf_giop_sequence_length = -1; +static int hf_giop_profile_id = -1; +static int hf_giop_type_id = -1; +static int hf_giop_iiop_v_maj = -1; +static int hf_giop_iiop_v_min = -1; +static int hf_giop_endianess = -1; /* esp encapsulations */ +static int hf_giop_IOR_tag = -1; +static int hf_giop_IIOP_tag = -1; + +static int hf_giop_TCKind = -1; +static int hf_giop_typecode_count = -1; +static int hf_giop_typecode_default_used = -1; +static int hf_giop_typecode_digits = -1; +static int hf_giop_typecode_length = -1; +static int hf_giop_typecode_max_length = -1; +static int hf_giop_typecode_member_name = -1; +static int hf_giop_typecode_name = -1; +static int hf_giop_typecode_scale = -1; +static int hf_giop_typecode_ValueModifier = -1; +static int hf_giop_typecode_Visibility = -1; + +static int hf_giop_type_boolean = -1; +static int hf_giop_type_char = -1; +static int hf_giop_type_double = -1; +static int hf_giop_type_enum = -1; +static int hf_giop_type_float = -1; +static int hf_giop_type_long = -1; +static int hf_giop_type_octet = -1; +static int hf_giop_type_short = -1; +static int hf_giop_type_string = -1; +static int hf_giop_type_ulong = -1; +static int hf_giop_type_ushort = -1; + +static int hf_giop_iiop_host = -1; +static int hf_giop_iiop_port = -1; +static int hf_giop_iop_vscid = -1; +static int hf_giop_iop_scid = -1; + +/* + * (sub)Tree declares + */ static gint ett_giop = -1; static gint ett_giop_reply = -1; @@ -53,6 +467,15 @@ static gint ett_giop_locate_request = -1; static gint ett_giop_locate_reply = -1; static gint ett_giop_fragment = -1; + +/* GIOP endianess */ + +static const value_string giop_endianess_vals[] = { + { 0x0, "Big Endian" }, + { 0x1, "Little Endian" }, + { 0, NULL} +}; + static const value_string sync_scope[] = { { 0x0, "SYNC_NONE" }, { 0x1, "SYNC_WITH_TRANSPORT"}, @@ -61,6 +484,15 @@ static const value_string sync_scope[] = { { 0, NULL} }; +/* Profile ID's */ + +static const value_string profile_id_vals[] = { + { 0x0, "TAG_INTERNET_IOP" }, + { 0x1, "TAG_MULTIPLE_COMPONENTS"}, + { 0x2, "TAG_SCCP_IOP"}, + { 0, NULL} +}; + static const value_string giop_message_types[] = { { 0x0, "Request" }, { 0x1, "Reply"}, @@ -83,233 +515,1639 @@ static const value_string giop_locate_status_types[] = { { 0, NULL } }; +static const value_string tckind_vals[] = { + { 0, "tk_null"}, + { 1, "tk_void"}, + { 2, "tk_short"}, + { 3, "tk_long"}, + { 4, "tk_ushort"}, + { 5, "tk_ulong"}, + { 6, "tk_float"}, + { 7, "tk_double"}, + { 8, "tk_boolean"}, + { 9, "tk_char"}, + { 10, "tk_octet"}, + { 11, "tk_any"}, + { 12, "tk_TypeCode"}, + { 13, "tk_Principal"}, + { 14, "tk_objref"}, + { 15, "tk_struct"}, + { 16, "tk_union"}, + { 17, "tk_enum"}, + { 18, "tk_string"}, + { 19, "tk_sequence"}, + { 20, "tk_array"}, + { 21, "tk_alias"}, + { 22, "tk_except"}, + { 23, "tk_longlong"}, + { 24, "tk_ulonglong"}, + { 25, "tk_longdouble"}, + { 26, "tk_wchar"}, + { 27, "tk_wstring"}, + { 28, "tk_fixed"}, + { 29, "tk_value"}, + { 30, "tk_value_box"}, + { 31, "tk_native"}, + { 32, "tk_abstract_interface"}, + { 0, NULL } +}; + + + +#define GIOP_MAGIC "GIOP" /* - * GIOP / IIOP types definition - OMG CORBA 2.x / GIOP 1.[012] - * See CORBA 2.4 specification: http://cgi.omg.org/cgi-bin/doc?formal/00-10-1 + * TAGS for IOR Profiles * - * Notes on mapping: + * Chapter 13 Corba 2.4.2 * - * <sequence> : unsigned int (# elts) + elements - * <string> : unsigned int (string length) + length characters (with '\0') - * <enum> : unsigned int (from 0 to n) */ -#define GIOP_MAGIC "GIOP" +#define IOP_TAG_INTERNET_IOP 0 +#define IOP_TAG_MULTIPLE_COMPONENTS 1 + + +/* Max Supported versions */ + static const guint GIOP_MAJOR = 1; static const guint GIOP_MINOR = 2; -static const gint GIOP_HEADER_SIZE = 12; static const int KeyAddr = 0; static const int ProfileAddr = 1; static const int ReferenceAddr = 2; -typedef struct OctetSequence + + +static const value_string reply_status_types[] = { + { NO_EXCEPTION, "No Exception" } , + { USER_EXCEPTION, "User Exception" } , + { SYSTEM_EXCEPTION, "System Exception" } , + { LOCATION_FORWARD, "Location Forward" } , + { LOCATION_FORWARD_PERM, "Location Forward Perm" } , + { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } , + { 0, NULL } +}; + + + +typedef enum LocateStatusType { - guint32 sequence_length; - guint8 sequence_data[1]; /* of length bytes */ + UNKNOWN_OBJECT, + OBJECT_HERE, + OBJECT_FORWARD, + OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */ + LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */ + LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */ +} +LocateStatusType_t; + +typedef struct LocateReplyHeader +{ + guint32 request_id; + guint32 locate_status; +} +LocateReplyHeader_t; + + +/* + * DATA - complete_request_list + */ + +static GList *giop_complete_request_list; + +struct comp_req_list_entry { + guint32 fn; /* frame number */ + gchar * operation; /* echo echoString */ + giop_sub_handle_t *subh; /* handle to sub dissector */ + guint32 reqid; /* request id */ + gchar * repoid; /* repository ID */ +}; + +typedef struct comp_req_list_entry comp_req_list_entry_t; + + +/* + * DATA - complete_reply_hash + * + * Maps reply FN to request MFN + */ + +static int complete_reply_hash_count = 1000; /* storage size for our permanent data */ + /* ie: 1000 entries -- needs tweaking -- FS */ + +struct complete_reply_hash_key { + guint32 fn; /* reply frame number */ +}; + +struct complete_reply_hash_val { + guint32 mfn; /* matching frame number (request) */ +}; + +GHashTable *giop_complete_reply_hash = NULL; /* hash */ +GMemChunk *giop_complete_reply_keys = NULL; /* key storage */ +GMemChunk *giop_complete_reply_vals = NULL; /* val storage */ + + +/* + * DATA - Module Hash stuff to store data from register_giop_user_module + * + * ie: module (or interface ?) name, and ptr to sub_dissector handle + * + * With this knowledge, we can call a sub dissector directly, + * by : + * + * objkey -> repoid -> sub_dissector via registered module/interface + * + */ + + +static int giop_module_init_count = 100; /* storage size for our permanent data */ + /* ie: 100 entries -- needs tweaking -- FS */ + +struct giop_module_key { + gchar *module; /* module (interface?) name */ +}; + +struct giop_module_val { + giop_sub_handle_t *subh; /* handle to sub dissector */ + /* gchar *idlname; */ /* idl dissector name */ +}; + +GHashTable *giop_module_hash = NULL; /* hash */ +GMemChunk *giop_module_keys = NULL; /* key storage */ +GMemChunk *giop_module_vals = NULL; /* val storage */ + + +/* + * DATA - GSList to store list of function (dissector) pointers. + * for heuristic dissection. + * + */ + +static GSList *giop_sub_list = NULL; + +/* + * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY + * to a REQUEST (resolve), we can dump/store the RepoId and Object Key. + * + * With this knowledge, we can call a sub dissector directly later + * by : + * + * objkey -> repoid -> sub_dissector via registered module/interface + * + * rather than heuristic calls that do not provide operation context. + * (unless we pass the RepoID for a given objkey -- hmmm) + * + */ + +/* + * Interesting operation list, add more if you want to save + * interesting data. + */ + +static const char giop_op_resolve[] = "resolve"; +static const char giop_op_bind_new_context[] = "bind_new_context"; +static const char giop_op_bind[] = "bind"; + +/* + * Enums for interesting local operations, that we may need to monitor + * with their subsequent replies + * + */ + +enum giop_op_val { + request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/ + request_bind_new_context_op_val, /* bind_new_context */ + request_bind_op_val, /* bind */ + request_get_INIT_op_val, /* finding Nameserver */ + +}; + + +/* + * hash for mapping object keys onto object namespaces, so + * I can call the correct dissector. + * + * + */ + +/* + * Where did I get the IOR from. + */ + +enum ior_src { + req_res = 0, /* REQUEST (resolve) */ + file, /* stringified IOR' in a file */ + +}; + +typedef enum ior_src ior_src_t; + + + +/* + * Enums for my lists and hash's + */ + +enum collection_data { + cd_heuristic_users = 0, + cd_module_hash, + cd_objkey_hash, + cd_complete_request_list, + cd_complete_reply_hash +}; + +typedef enum collection_data collection_data_t; + + + + +static int giop_objkey_init_count = 100; /* storage size for our permanent data */ + /* ie: 100 entries -- needs tweaking -- FS */ + +struct giop_object_key { + guint8 *objkey; /* ptr to object key */ + guint32 objkey_len; /* length */ +}; + +struct giop_object_val { + guint8 *repo_id; /* ptr to Repository ID string */ + ior_src_t src; /* where did Iget this IOR from */ +}; + +GHashTable *giop_objkey_hash = NULL; /* hash */ +GMemChunk *giop_objkey_keys = NULL; /* key storage */ +GMemChunk *giop_objkey_vals = NULL; /* val storage */ + + + +/* + * ------------------------------------------------------------------------------------------+ + * Private helper functions + * ------------------------------------------------------------------------------------------+ + */ + + + +/* + * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet. + */ + +static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) { + GList * newlist_start; + comp_req_list_entry_t * entry = NULL; + gchar * opn; + + entry = g_malloc(sizeof(comp_req_list_entry_t)); + opn = g_strdup(op); /* duplicate operation for storage */ + + entry->fn = fn; + entry->reqid = reqid; + entry->subh = sh; + entry->operation = opn; + entry->repoid = NULL; /* dont have yet */ + + newlist_start = g_list_append (list, entry); /* append */ + + return newlist_start; +} + + +/* + * Used to find an entry with matching Frame Number FN + * in the complete_request_list list. + */ + +static comp_req_list_entry_t * find_fn_in_list(guint32 fn) { + + GList * element; /* entry in list */ + comp_req_list_entry_t * entry_ptr = NULL; + + element = g_list_last(giop_complete_request_list); /* start from last */ + + while(element) { /* valid list entry */ + entry_ptr = element->data; /* grab data pointer */ + if (entry_ptr->fn == fn) { /* similar FN */ + return entry_ptr; + } + element = g_list_previous(element); /* try next previous */ + } + + return NULL; /* no match so return NULL */ +} + + +/* + * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list + * + * Call this when you know a FN and matching giop_sub_handle_t and repoid + * + * This is done in say, try_explicit_dissector for example. + * + */ + +static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) { + + comp_req_list_entry_t * entry = NULL; + entry = find_fn_in_list(fn); /* grab FN data entry */ + + if (entry) { + entry->subh = sh; + entry->repoid = g_strdup(repoid); /* copy and store */ + + } +} + + + + +/* giop_complete_reply_hash "EQUAL" Functions */ + +static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) { + struct complete_reply_hash_key *mk1 = (struct complete_reply_hash_key *)v; + struct complete_reply_hash_key *mk2 = (struct complete_reply_hash_key *)w; + + if (mk1->fn == mk2->fn) { + return 1; + } + + return 0; /* found differences */ +} + +/* giop_complete_reply_hash "HASH" Functions */ + +static guint32 complete_reply_hash_fn(gconstpointer v) { + guint32 val; /* init hash value */ + struct complete_reply_hash_key *key = (struct complete_reply_hash_key *)v; + + val = key->fn; /* simple and unique */ + + return val; +} + + +/* + * Insert the FN and MFN together in our complete_reply_hash. + */ + +static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) { + + struct complete_reply_hash_key key, *new_key; + struct complete_reply_hash_val *val = NULL; + + key.fn = fn; + + val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key); + + if (val) { + return; /* FN collision */ + } + + new_key = g_mem_chunk_alloc(giop_complete_reply_keys); + new_key->fn = fn; /* save FN */ + + val = g_mem_chunk_alloc(giop_complete_reply_vals); + val->mfn = mfn; /* and MFN */ + + g_hash_table_insert(giop_complete_reply_hash, new_key, val); + +} + +/* + * Find the MFN values from a given FN key. + * Assumes the complete_reply_hash is already populated. + */ + +static guint32 get_mfn_from_fn(guint32 fn) { + + struct complete_reply_hash_key key; + struct complete_reply_hash_val *val = NULL; + guint32 mfn = fn; /* save */ + + key.fn = fn; + val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key); + + if (val) { + mfn = val->mfn; /* grab it */ + } + + return mfn; /* mfn or fn if not found */ + +} + +/* + * Attempt to find the MFN for this FN, and return it. + * Return MFN if found, or just FN if not. This is + * only used when we are building + */ + +static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) { + + GList * element; /* last entry in list */ + comp_req_list_entry_t * entry_ptr = NULL; + + /* Need Some pretty snappy code */ + + /* Loop back from current end of complete_request_list looking for */ + /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */ + + /* + * As this routine is only called during initial pass of data, + * and NOT when a user clicks, it is ok to start from Current + * end of complete_request_list when searching for a match. + * As that list is bing populated in the same order as FN's + * are being read. + * + * Also, can make check for same reqid more detailed, but I start + * with reqid. Could add say port or address checks etc later ?? + */ + + + element = g_list_last(giop_complete_request_list); /* get last */ + + while(element) { /* valid list entry */ + entry_ptr = element->data; /* grab data pointer */ + if (entry_ptr->reqid == reqid) { /* similar reqid */ + return entry_ptr->fn; /* return MFN */ + } + element = g_list_previous(element); /* try next previous */ + } + + return fn; /* no match so return FN */ +} + + +/* Module Hash "EQUAL" Functions */ + +static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) { + struct giop_module_key *mk1 = (struct giop_module_key *)v; + struct giop_module_key *mk2 = (struct giop_module_key *)w; + + if (!strcmp(mk1->module, mk2->module)) { + return 1; + } + + return 0; /* found differences */ +} + +/* Module Hash "HASH" Functions */ + +static guint32 giop_hash_module_hash(gconstpointer v) { + + int i,len; + guint32 val = 0; /* init hash value */ + + struct giop_module_key *key = (struct giop_module_key *)v; + + /* + * Hmm, try this simple hashing scheme for now. + * ie: Simple summation, FIX later -- FS + * + * + */ + + len = strlen(key->module); + + for (i=0; i<len; i++) { + val += (guint8) key->module[i]; + } + + return val; + +} + + +/* + * ------------------------------------------------------------------------------------------+ + * Public Utility functions + * ------------------------------------------------------------------------------------------+ + */ + + + + +/* + * Routine to allow giop users to register their sub dissector function, name, and + * IDL module/interface name. Store in giop_module_hash. + * + * This is used by try_explicit_giop_dissector() to find the + * correct sub-dissector. + * + */ + +void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module) { + + struct giop_module_key module_key, *new_module_key; + struct giop_module_val *module_val = NULL; + + module_key.module = module; /* module name */ + + module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key); + + if (module_val) { + return; /* module name collision */ + } + + /* So, passed module name should NOT exist in hash at this point.*/ + +#if DEBUG + printf("giop:register_module: Adding Module %s to module hash \n", module); + printf("giop:register_module: Module sub dissector name is %s \n", name); +#endif + + new_module_key = g_mem_chunk_alloc(giop_module_keys); + new_module_key->module = module; /* save Module or interface name from IDL */ + + module_val = g_mem_chunk_alloc(giop_module_vals); + + module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */ + + module_val->subh->sub_name = name; /* save dissector name */ + module_val->subh->sub_fn = sub; /* save subdissector*/ + + g_hash_table_insert(giop_module_hash, new_module_key, module_val); + +} + + + + +/* Object Key Hash "EQUAL" Functions */ + +static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) { + struct giop_object_key *v1 = (struct giop_object_key *)v; + struct giop_object_key *v2 = (struct giop_object_key *)w; + + if (v1->objkey_len != v2->objkey_len) + return 0; /* no match because different length */ + + /* Now do a byte comaprison */ + + if (!memcmp(v1->objkey,v2->objkey, v1->objkey_len)) { + return 1; /* compares ok */ + } + +#if DEBUG + printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match"); +#endif + + return 0; /* found differences */ +} + +/* Object Key Hash "HASH" Functions */ + +static guint32 giop_hash_objkey_hash(gconstpointer v) { + struct giop_object_key *key = (struct giop_object_key *)v; + + int i; + guint32 val = 0; /* init hash value */ + + + /* + * Hmm, try this simple hashing scheme for now. + * ie: Simple summation + * + * + */ + +#if DEBUG + printf("giop:hash_objkey: Key length = %u \n", key->objkey_len ); +#endif + + for (i=0; i< key->objkey_len; i++) { + val += (guint8) key->objkey[i]; + } + + return val; + +} + +/* + * Routine to take an object key octet sequence, and length, and ptr to + * a (null terminated )repository ID string, and store them in the obect key hash. + * + * Blindly Inserts even if it does exist, See TODO at top for reason. + */ + +static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) { + + struct giop_object_key objkey_key, *new_objkey_key; + struct giop_object_val *objkey_val = NULL; + + objkey_key.objkey_len = len; /* length */ + objkey_key.objkey = obj; /* object key octet sequence */ + + /* Look it up to see if it exists */ + + objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key); + + /* CHANGED -- Same reqid, so abandon old entry */ + + if (objkey_val) { + g_hash_table_remove(hash, &objkey_key); + } + + /* So, passed key should NOT exist in hash at this point.*/ + + new_objkey_key = g_mem_chunk_alloc(giop_objkey_keys); + new_objkey_key->objkey_len = len; /* save it */ + new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */ + + objkey_val = g_mem_chunk_alloc(giop_objkey_vals); + objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */ + objkey_val->src = src; /* where IOR came from */ + + +#if DEBUG + printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n", + objkey_val->repo_id, new_objkey_key->objkey_len); +#endif + + g_hash_table_insert(hash, new_objkey_key, objkey_val); + +} + + + +/* + * convert an ascii char representing a hex value, + * to a numeric value. + * + * returns value, or -1 if problem. + * + */ + +static gint8 hex_char_to_val(guchar c){ + gint8 retval ; + + if (!isxdigit(c)) { + return -1; + } + if (isdigit(c)) { + retval = c - 48; /* convert digit */ + return retval; + } + + c = toupper(c); /* convert to uppercase */ + if (c >= 'A' && c <= 'F') { + retval = c - 55; + return retval; + } + else { + return -1; + } + +} + +/* + * Convert from stringified IOR of the kind IOR:af4f7e459f.... + * to an IOR octet sequence. + * + * User must free buffer. + * + * Creates a new tvbuff and call decode_IOR with a NULL tree, just to + * grab repoid etc for our objkey hash. + * + */ + +static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){ + gint8 tmpval_lsb; + gint8 tmpval_msb; + gint8 tmpval; /* complete value */ + int i; + + *out = g_new0(guint8, in_len); /* allocate buffer */ + + if (*out == NULL) { + return 0; + } + + /* skip past IOR: and convert character pairs to guint8 */ + + for (i=4; i<in_len-1; i+=2) { + if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */ + + if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) { + } + + if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) { + } + + tmpval = tmpval_msb << 4; + tmpval += tmpval_lsb; + (*out)[(i-4)/2] = (guint8) tmpval; + + } + else { + /* hmm */ + break; + } + + } + + return (i-4)/2; /* length */ + +} + + + +/* + * Simple getline, copied from somewhere :) + * + */ + +static int getline(FILE *fp, gchar *line, int maxlen) { + + if (fgets(line,maxlen,fp) == NULL) + return 0; + else + return strlen(line); + } -OctetSequence; -typedef OctetSequence Principal; -typedef OctetSequence String; /* - * Some structures that contain sequences can not be directly used - * (alignment problem on 64 bit architectures) + * Read a list of stringified IOR's from a named file, convert to IOR's + * and store in object key hash */ -typedef struct ServiceContext -{ - guint32 context_id; - OctetSequence context_data; +static void read_IOR_strings_from_file(gchar *name, int max_iorlen) { + guchar *buf = NULL; /* NOTE reused for every line */ + int len; + int ior_val_len; /* length after unstringifying. */ + FILE *fp; + guint8 *out = NULL; /* ptr to unstringified IOR */ + tvbuff_t *tvb = NULL; /* temp tvbuff for dissectin IORs */ + guint32 my_offset = 0; + gboolean stream_is_big_endian; + + + fp = fopen(name,"r"); /* open read only */ + + if (fp == NULL) { + if (errno == EACCES) + fprintf(stderr, "Error opening file IOR.txt for reading: %s \n",strerror(errno)); + return; + } + + buf = g_malloc0(max_iorlen+1); /* input buf */ + + while ((len = getline(fp,buf,max_iorlen+1)) > 0) { + my_offset = 0; /* reset for every IOR read */ + + ior_val_len = string_to_IOR(buf,len,&out); /* convert */ + + if(ior_val_len>0) { + + /* Combination of tvb_new() and tvb_set_real_data(). Can throw ReportedBoundsError. */ + + tvb = tvb_new_real_data(out,ior_val_len,ior_val_len, "GIOP FILE IOR"); + + stream_is_big_endian = !get_CDR_octet(tvb,&my_offset); + decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian); + + tvb_free(tvb); + + } + } + + fclose(fp); /* be nice */ + + g_free(out); + g_free(buf); } -ServiceContext; -typedef struct ServiceContextList -{ - guint32 nr_context; - ServiceContext service_context[1]; /* nr_context elements */ + + +/* + * Init routine, setup our request hash stuff, or delete old ref's + * + * Cannot setup the module hash here as my init() may not be called before + * users start registering. So I will move the module_hash stuff to + * proto_register_giop, as is done with packet-rpc + * + * + * + * Also, setup our objectkey/repoid hash here. + * + */ + +static void giop_init(void) { + + + /* + * Create objkey/repoid hash, use my "equal" and "hash" functions. + * + */ + + if (giop_objkey_hash) + g_hash_table_destroy(giop_objkey_hash); + if (giop_objkey_keys) + g_mem_chunk_destroy(giop_objkey_keys); + if (giop_objkey_vals) + g_mem_chunk_destroy(giop_objkey_vals); + + + /* + * Create hash, use my "equal" and "hash" functions. + * + */ + + giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal); + + giop_objkey_keys = g_mem_chunk_new("giop_objkey_keys", + sizeof(struct giop_object_key), + giop_objkey_init_count * sizeof(struct giop_object_key), + G_ALLOC_AND_FREE); + + giop_objkey_vals = g_mem_chunk_new("giop_objkey_vals", + sizeof(struct giop_object_val), + giop_objkey_init_count * sizeof(struct giop_object_val), + G_ALLOC_AND_FREE); + + + /* + * Create complete_reply_hash, use my "equal" and "hash" functions. + * + */ + + if (giop_complete_reply_hash) + g_hash_table_destroy(giop_complete_reply_hash); + if (giop_complete_reply_keys) + g_mem_chunk_destroy(giop_complete_reply_keys); + if (giop_complete_reply_vals) + g_mem_chunk_destroy(giop_complete_reply_vals); + + + /* + * Create hash, use my "equal" and "hash" functions. + * + */ + + giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn); + + giop_complete_reply_keys = g_mem_chunk_new("giop_complete_reply_keys", + sizeof(struct complete_reply_hash_key), + complete_reply_hash_count * sizeof(struct complete_reply_hash_key), + G_ALLOC_AND_FREE); + + giop_complete_reply_vals = g_mem_chunk_new("giop_complete_reply_vals", + sizeof(struct complete_reply_hash_val), + complete_reply_hash_count * sizeof(struct complete_reply_hash_val), + G_ALLOC_AND_FREE); + + + + read_IOR_strings_from_file("IOR.txt", 600); /* testing */ + + } -ServiceContextList; -typedef enum MsgType -{ - Request, - Reply, - CancelRequest, - LocateRequest, - LocateReply, - CloseConnection, - MessageError, - Fragment /* GIOP 1.1 only */ -} -MsgType; - -typedef struct Version -{ - guint8 major; - guint8 minor; + +/* + * Insert an entry in the GIOP User table. + * Uses a GList. + * Uses giop_sub_handle_t to wrap giop user info. + * + */ + +void register_giop_user(giop_sub_dissector_t *sub, gchar *name) { + + giop_sub_handle_t *subh; + + subh = g_malloc(sizeof (giop_sub_handle_t)); + + subh->sub_name = name; + subh->sub_fn = sub; + + giop_sub_list = g_slist_append (giop_sub_list, subh); + } -Version; -typedef struct MessageHeader -{ - guint8 magic[4]; - Version GIOP_version; - guint8 flags; /* byte_order in 1.0 */ - guint8 message_type; - guint32 message_size; + +/* + * Lookup an object key in our object key hash, and return the corresponding + * Repo Id. + * + */ + +static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) { + + struct giop_object_key objkey_key; + struct giop_object_val *objkey_val = NULL; + + objkey_key.objkey_len = len; /* length */ + objkey_key.objkey = obj; /* object key octet sequence */ + + /* Look it up to see if it exists */ + + objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key); + + if (objkey_val) { +#if DEBUG + printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id ); +#endif + return objkey_val->repo_id; /* found */ + } + +#if DEBUG + printf("FAILED Lookup of object key \n" ); +#endif + + return NULL; /* not found */ } -MessageHeader; -typedef struct RequestHeader_1_0 -{ - /* ServiceContextList service_context; */ - guint32 request_id; - guint8 response_expected; - OctetSequence object_key; - /* String operation; */ - /* Principal requesting_principal; */ + + +/* + * Extract top level module/interface from repoid + * + * eg from - "IDL:Echo/interface1:1.0" + * get "Echo" + * + * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get + * get linux.org/Penguin/Teeth + * + * + * User must free returned ptr after use. + * + * TODO -- generalize for other Repoid encodings + */ + +static gchar * get_modname_from_repoid(gchar *repoid) { + + gchar *modname = NULL; + gchar *saved_repoid = NULL; + gchar c = 'a'; + guint8 stop_mod; /* Index of last character of modname in Repoid */ + guint8 start_mod = 4; /* Index where Module name starts in repoid */ + int i; + + saved_repoid = g_strdup(repoid); /* make a copy */ + + /* Must start with IDL: , otherwise I get confused */ + + if (g_strncasecmp("IDL:",repoid,4)) + return NULL; + + /* Looks like a RepoID to me, so get Module or interface name */ + + /* TODO -- put some code here to get Module name */ + + for(i=4; c != '\0'; i++) { + c = repoid[i]; + stop_mod = i; /* save */ + if (c == ':' ) /* delimiters */ + break; + + } + + /* Now create a new string based on start and stop and \0 */ + + modname = g_strndup(repoid+4, stop_mod - start_mod); + + return modname; + } -RequestHeader_1_0; -typedef struct RequestHeader_1_1 -{ - /* ServiceContextList service_context; */ - guint32 request_id; - guint8 response_expected; - guint8 reserved[3]; - OctetSequence object_key; - /* String operation; */ - /* Principal requesting_principal; */ +/* + * DEBUG CODE + * + */ + + +#if DEBUG + +/* + * Display a "module" hash entry + */ + +static void display_module_hash(gpointer key, gpointer val, gpointer user_data) { + + struct giop_module_val *mv = (struct giop_module_val *) val; + struct giop_module_key *mk = (struct giop_module_key *) key; + + printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name); + + return; + } -RequestHeader_1_1; -typedef enum ReplyStatusType -{ - NO_EXCEPTION, - USER_EXCEPTION, - SYSTEM_EXCEPTION, - LOCATION_FORWARD, - LOCATION_FORWARD_PERM, /* new for GIOP 1.2 */ - NEEDS_ADDRESSING_MODE /* new for GIOP 1.2 */ +/* + * Display a "complete_reply " hash entry + */ + +static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) { + + struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val; + struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key; + + printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn); + + return; + } -ReplyStatusType; -static const value_string reply_status_types[] = { - { NO_EXCEPTION, "No Exception" } , - { USER_EXCEPTION, "User Exception" } , - { SYSTEM_EXCEPTION, "System Exception" } , - { LOCATION_FORWARD, "Location Forward" } , - { LOCATION_FORWARD_PERM, "Location Forward Perm" } , - { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } , - { 0, NULL } -}; -typedef struct ReplyHeader -{ - /* ServiceContext service_context; */ - guint32 request_id; - guint32 reply_status; +/* + * Display an "objkey" hash entry + */ + +static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) { + int i; + struct giop_object_val *mv = (struct giop_object_val *) val; + struct giop_object_key *mk = (struct giop_object_key *) key; + + + printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len); + + for (i=0; i<mk->objkey_len; i++) { + printf("%.2x ", mk->objkey[i]); + } + + /* + * If read from file, mark it as such.. + */ + + if(mv->src == 0) { + printf(", Repo ID = %s \n", mv->repo_id); + } + else { + printf(", Repo ID = %s , (file) \n", mv->repo_id); + } + + return; + } -ReplyHeader; -typedef struct SystemExceptionReplyBody -{ - String exception_id; - u_int minor_code_value; - u_int completion_status; +/* + * Display all giop_sub_list (GSList) entries + */ + +static void display_heuristic_user_list() { + int i; + int len; + giop_sub_handle_t *subh; /* handle */ + + /* Get length of list */ + len = g_slist_length(giop_sub_list); /* find length */ + + if (len == 0) + return; + + for (i=0; i<len; i++) { + subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */ + printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name); + } + } -SystemExceptionReplyBody; -typedef struct CancelRequestHeader -{ - guint32 request_id; +/* + * Display all complete_request_list (GList) entries + */ + +static void display_complete_request_list() { + int i; + int len; + comp_req_list_entry_t *entry; + + /* Get length of list */ + len = g_list_length(giop_complete_request_list); /* find length */ + + if (len == 0) + return; + + for (i=0; i<len; i++) { + entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */ + printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn, + entry->reqid,entry->operation, entry->repoid); + } + } -CancelRequestHeader; -typedef struct LocateRequestHeader -{ - guint32 request_id; - OctetSequence object_key; + + + +/* Dump Hash/List contents + * + * collection_type specifies the list or hash to dump + * + */ + +static void giop_dump_collection(collection_data_t collection_type) { + + switch(collection_type) { + case cd_heuristic_users: + printf("+----------------------------------------------+ \n"); + printf("+-------------- Heuristic User (Begin) --------+ \n"); + printf("+----------------------------------------------+ \n"); + + display_heuristic_user_list(); + + printf("+----------------------------------------------+ \n"); + printf("+-------------- Heuristic User (End) ----------+ \n"); + printf("+----------------------------------------------+ \n"); + + break; + + case cd_complete_request_list: + printf("+----------------------------------------------+ \n"); + printf("+------------- Complete Request List (Begin) --+ \n"); + printf("+----------------------------------------------+ \n"); + + display_complete_request_list(); + + printf("+----------------------------------------------+ \n"); + printf("+------------ Complete Request List (End) -----+ \n"); + printf("+----------------------------------------------+ \n"); + + break; + + case cd_module_hash: + printf("+----------------------------------------------+ \n"); + printf("+-------------- Module (Begin) ----------------+ \n"); + printf("+----------------------------------------------+ \n"); + + g_hash_table_foreach(giop_module_hash, display_module_hash, NULL); + + printf("+----------------------------------------------+ \n"); + printf("+-------------- Module ( End) -----------------+ \n"); + printf("+----------------------------------------------+ \n\n"); + + break; + + case cd_objkey_hash: + printf("+----------------------------------------------+ \n"); + printf("+-------------- Objkey (Begin) ----------------+ \n"); + printf("+----------------------------------------------+ \n"); + + g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL); + + printf("+----------------------------------------------+ \n"); + printf("+-------------- Objkey (End) ------------------+ \n"); + printf("+----------------------------------------------+ \n\n"); + + break; + + case cd_complete_reply_hash: + printf("+----------------------------------------------+ \n"); + printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n"); + printf("+----------------------------------------------+ \n"); + + g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL); + + printf("+----------------------------------------------+ \n"); + printf("+------------- Complete_Reply_Hash (End) ------+ \n"); + printf("+----------------------------------------------+ \n"); + + break; + + default: + + printf("giop: giop_dump_collection: Unknown type \n"); + + } + + } -LocateRequestHeader; -typedef enum LocateStatusType -{ - UNKNOWN_OBJECT, - OBJECT_HERE, - OBJECT_FORWARD, - OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */ - LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */ - LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */ + +#endif /* DEBUG */ + +/* + * Loop through all subdissectors, and call them until someone + * answers (returns TRUE). This function then returns TRUE, otherwise + * it return FALSE + */ + +gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + MessageHeader *header, gchar *operation ) { + + int i,len; + gboolean res = FALSE; /* result of calling a heuristic sub dissector */ + giop_sub_handle_t *subh = NULL; + + len = g_slist_length(giop_sub_list); /* find length */ + + if (len == 0) + return FALSE; + + for (i=0; i<len; i++) { + subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */ + res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */ + if (res) { + return TRUE; /* found one, lets return */ + } + } + return res; /* result */ + } -LocateStatusType; -typedef struct LocateReplyHeader -{ - guint32 request_id; - guint32 locate_status; + +/* + * Find the matching repoid in the module hash and call + * the dissector function if offset exists. + * + * + * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors + * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth". + * + * + * + */ + +static void try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + MessageHeader *header, gchar *operation, gchar *repoid ) { + + giop_sub_handle_t *subdiss = NULL; /* handle */ + gboolean res; + gchar *modname = NULL; + struct giop_module_key module_key; + struct giop_module_val *module_val = NULL; + + + /* + * Get top level module/interface from complete repoid + */ + + modname = get_modname_from_repoid(repoid); + + + /* Search for Module or interface name */ + + module_key.module = modname; /* module name */ + module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key); + + if (module_val == NULL) { + return; /* module not registered */ + } + + subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */ + + if (subdiss) { + /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */ + /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */ + /* but only if user not clicking */ + + if (!pinfo->fd->flags.visited) + add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid); + + + /* Call subdissector if current offset exists */ + + if (tvb_offset_exists(tvb, *offset)) { +#if DEBUG + printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname); +#endif + res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */ + } /* offset exists */ + } /* subdiss */ + + return; } -LocateReplyHeader; -/* Take in a string and replace non-printable characters with periods */ -static void -printable_string (gchar *in, guint32 len) -{ - guint32 i = 0; - for(i=0; i < len; i++) - { - if( !isprint( (unsigned char)in[i] ) ) - in[i] = '.'; + +/* Take in an array of char and create a new string. + * Replace non-printable characters with periods. + * + * The array may contain \0's so dont use strdup + * The string is \0 terminated, and thus longer than + * the initial sequence. + * Caller must free the new string. + */ + +static gchar * make_printable_string (gchar *in, guint32 len) { + int i = 0; + gchar *print_string = NULL; + + print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */ + memcpy(print_string, in, len); /* and make a copy of input data */ + + for(i=0; i < len; i++) { + if( !isprint( (unsigned char)print_string[i] ) ) + print_string[i] = '.'; } + + return print_string; /* return ptr */ } /* Determine the byte order from the GIOP MessageHeader */ -static gboolean -is_big_endian (MessageHeader * header) -{ + +gboolean is_big_endian (MessageHeader * header) { gboolean big_endian = FALSE; - switch (header->GIOP_version.minor) - { - case 2: - case 1: - if (header->flags & 0x01) - big_endian = FALSE; - else - big_endian = TRUE; - break; - case 0: - if (header->flags) - big_endian = FALSE; - else - big_endian = TRUE; - break; - default: - break; - } + switch (header->GIOP_version.minor) { + case 2: + case 1: + if (header->flags & 0x01) + big_endian = FALSE; + else + big_endian = TRUE; + break; + case 0: + if (header->flags) + big_endian = FALSE; + else + big_endian = TRUE; + break; + default: + break; + } return big_endian; } + + +/* + * Calculate new offset, based on the current offset, and user supplied + * "offset delta" value, and the alignment requirement. + * + * + * + * eg: Used for GIOP 1.2 where Request and Reply bodies are + * aligned on 8 byte boundaries. + */ + +static void set_new_alignment(int *offset, int delta, int alignment) { + + while( ( (*offset + delta) % alignment) != 0) + ++(*offset); + + +} + + + +/* + * ------------------------------------------------------------------------------------------+ + * Public get_CDR_xxx functions. + * ------------------------------------------------------------------------------------------+ + */ + + + +/* + * Gets data of type any. This is encoded as a TypeCode + * followed by the encoded value. + */ + +void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, int boundary, + MessageHeader * header ) { + + guint32 TCKind; /* TypeCode */ + + /* get TypeCode of any */ + TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header ); + + /* dissect data of type TCKind */ + dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind ); +} + + +/* Copy a 1 octet sequence from the tvbuff + * which represents a boolean value, and convert + * it to a boolean value. + * Offset is then incremented by 1, to indicate the 1 octet which + * has been processed. + */ + +gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) { + guint8 val; + + val = tvb_get_guint8(tvb, *offset); /* easy */ + (*offset)++; + return val; +} + +/* Copy a 1 octet sequence from the tvbuff + * which represents a char, and convert + * it to an char value. + * offset is then incremented by 1, to indicate the 1 octet which + * has been processed. + */ + +guint8 get_CDR_char(tvbuff_t *tvb, int *offset) { + guint8 val; + + val = tvb_get_guint8(tvb, *offset); /* easy */ + (*offset)++; + return val; +} + + + +/* + * Floating Point Data Type double IEEE 754-1985 + * + * Copy an 8 octet sequence from the tvbuff + * which represents a double value, and convert + * it to a double value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for double values. + * offset is then incremented by 8, to indicate the 8 octets which + * have been processed. + */ + +gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) { + + guint8 sign; + guint8 e1,e2,f1,f2,f3,f4,f5,f6,f7; + gdouble val; + guint16 exp; + guint32 fract0, fract1; + gdouble d_fract; + + + /* double values must be aligned on a 8 byte boundary */ + + while( ( (*offset + boundary) % 8) != 0) + ++(*offset); + + + if(stream_is_big_endian) { + e1 = get_CDR_octet(tvb,offset); + sign = e1 >> 7; /* sign value */ + e1 &= 0x7f; /* bottom 7 bits */ + f1 = get_CDR_octet(tvb,offset); + e2 = f1 >> 4; + f1 &= 0x0f; /* bottom 4 bits */ + f2 = get_CDR_octet(tvb,offset); + f3 = get_CDR_octet(tvb,offset); + f4 = get_CDR_octet(tvb,offset); + f5 = get_CDR_octet(tvb,offset); + f6 = get_CDR_octet(tvb,offset); + f7 = get_CDR_octet(tvb,offset); + + } else { + + f7 = get_CDR_octet(tvb,offset); + f6 = get_CDR_octet(tvb,offset); + f5 = get_CDR_octet(tvb,offset); + f4 = get_CDR_octet(tvb,offset); + f3 = get_CDR_octet(tvb,offset); + f2 = get_CDR_octet(tvb,offset); + f1 = get_CDR_octet(tvb,offset); + e2 = f1 >> 4; + f1 &= 0x0f; /* bottom 4 bits */ + e1 = get_CDR_octet(tvb,offset); + sign = e1 >> 7; /* sign value */ + e1 &= 0x7f; /* bottom 7 bits */ + + } + + exp = (e1 << 4) + e2; + + /* Now lets do some 52 bit math with 32 bit constraint */ + + fract0 = f7 + (f6 << 8) + (f5 << 16) + (f4 << 24); /* lower 32 bits of fractional part */ + fract1 = f3 + (f2 << 8) + (f1 << 16); /* top 20 bits of fractional part */ + + d_fract = (fract1 / (pow(2,20))) + (fract0 / (pow(2,52))); /* 52 bits represent a fraction */ + + val = pow(-1,sign) * pow(2,(exp - 1023)) * (1 + d_fract); + + return val; /* FIX rounding ?? */ + +} + + /* Copy a 4 octet sequence from the tvbuff - * which represents an unsigned long value, and convert - * it to an unsigned long vaule, taking into account byte order. + * which represents an enum value, and convert + * it to an enum value, taking into account byte order. * offset is first incremented so that it falls on a proper alignment - * boundary for unsigned long values. + * boundary for an enum (4) * offset is then incremented by 4, to indicate the 4 octets which * have been processed. + * + * Enum values are encoded as unsigned long. */ -static guint32 -get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian) -{ - guint32 val; + + +guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) { + + return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary ); + +} + + +/* + * Copy an "n" octet sequence from the tvbuff + * which represents a Fixed point decimal type, and convert + * it to a Fixed point decimal type. There are no alignment restrictions. + * Size of fixed decimal type is determined by IDL, but this routine + * will just process octets until it hits the "sign configuration" as + * the last octet. + * + * This value is either + * 0xd - positive value + * 0xc - negative value + * + * offset is then incremented past the sign octet. + * + * TODO - pass in parameters from IDL, eg: scale etc.. + * + */ + +void get_CDR_fixed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset, guint32 n) { + + +} + + +/* + * Floating Point Data Type float IEEE 754-1985 + * + * Copy an 4 octet sequence from the tvbuff + * which represents a float value, and convert + * it to a float value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for float values. + * offset is then incremented by 4, to indicate the 4 octets which + * have been processed. + */ + +gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) { + + guint8 sign; + guint8 e1,e2,f1,f2,f3; + gfloat val; + guint8 exp; + guint32 fract; + gdouble d_fract; + + /* float values must be aligned on a 4 byte boundary */ + + while( ( (*offset + boundary) % 4) != 0) + ++(*offset); + + if(stream_is_big_endian) { + e1 = get_CDR_octet(tvb,offset); + sign = e1 >> 7; /* sign value */ + e1 &= 0x7f; /* bottom 7 bits */ + f1 = get_CDR_octet(tvb,offset); + e2 = f1 >> 7; + f1 &= 0x7f; /* bottom 7 bits */ + f2 = get_CDR_octet(tvb,offset); + f3 = get_CDR_octet(tvb,offset); + + } else { + + f3 = get_CDR_octet(tvb,offset); + f2 = get_CDR_octet(tvb,offset); + f1 = get_CDR_octet(tvb,offset); + e2 = f1 >> 7; + f1 &= 0x7f; /* bottom 7 bits */ + e1 = get_CDR_octet(tvb,offset); + sign = e1 >> 7; /* sign value */ + e1 &= 0x7f; /* bottom 7 bits */ + + } + + + exp = (e1 << 1) + e2; + fract = f3 + (f2 << 8) + (f1 << 16); + + d_fract = fract / (pow(2,23)); /* 23 bits represent a fraction */ + + val = pow(-1,sign) * pow(2,(exp - 127)) * (1 + d_fract); + + return val; /* FIX rounding ?? */ + +} + + +/* + * Decode an Interface type, and display it on the tree. + */ + +void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + gboolean stream_is_big_endian, int boundary) { + + + decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian); + + return; +} + + +/* Copy a 4 octet sequence from the tvbuff + * which represents a signed long value, and convert + * it to an signed long vaule, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for long values. + * offset is then incremented by 4, to indicate the 4 octets which + * have been processed. + */ + +gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) { + + gint32 val; /* unsigned long values must be aligned on a 4 byte boundary */ - while( ( (*offset + GIOP_HEADER_SIZE) % 4) != 0) + while( ( (*offset + boundary) % 4) != 0) ++(*offset); val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) : @@ -319,21 +2157,69 @@ get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian) return val; } +/* + * Decode an Object type, and display it on the tree. + */ + +void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + gboolean stream_is_big_endian, int boundary) { + + decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian); + + return; +} + + +/* Copy a 1 octet sequence from the tvbuff + * which represents a octet, and convert + * it to an octet value. + * offset is then incremented by 1, to indicate the 1 octet which + * has been processed. + */ + +guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) { + guint8 val; + + val = tvb_get_guint8(tvb, *offset); /* easy */ + (*offset)++; + return val; +} + + +/* Copy a sequence of octets from the tvbuff. + * Caller of this function must remember to free the + * array pointed to by seq. + * This function also increments offset by len. + */ + +void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, int len) { + + if (! tvb_bytes_exist(tvb, *offset,len)) { + tvb_get_guint8(tvb,100000); /* generate an exception, and stop processing */ + /* better than a core dump later */ + } + + *seq = g_new0(gchar, len + 1); + tvb_memcpy( tvb, *seq, *offset, len); + *offset += len; +} + + /* Copy a 2 octet sequence from the tvbuff - * which represents an unsigned short value, and convert - * it to an unsigned short value, taking into account byte order. + * which represents a signed short value, and convert + * it to a signed short value, taking into account byte order. * offset is first incremented so that it falls on a proper alignment - * boundary for unsigned short values. + * boundary for short values. * offset is then incremented by 2, to indicate the 2 octets which * have been processed. */ -static guint16 -get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian) -{ - guint16 val; - /* unsigned short values must be aligned on a 2 byte boundary */ - while( ( (*offset + GIOP_HEADER_SIZE) % 2) != 0) +gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) { + + gint16 val; + + /* short values must be aligned on a 2 byte boundary */ + while( ( (*offset + boundary) % 2) != 0) ++(*offset); val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) : @@ -344,22 +2230,234 @@ get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian) } + +/* Copy an octet sequence from the tvbuff + * which represents a string, and convert + * it to an string value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for string values. (begins with an unsigned long LI) + * + * String sequence is copied to a buffer "seq". This must + * be freed by the calling program. + * offset is then incremented, to indicate the octets which + * have been processed. + * + * returns number of octets in the sequence + * + * Note: This function only supports single byte encoding at the + * moment until I get a handle on multibyte encoding etc. + * + */ + + +guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian, + int boundary ) { + + guint32 slength; + + slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */ + + /* Avoid crashing */ + + if (! tvb_bytes_exist(tvb, *offset, slength)) { + tvb_get_guint8(tvb,100000); /* generate an exception, and stop processing */ + /* better than a core dump later */ + } + +#if 0 + (*offset)++; /* must step past \0 delimiter */ +#endif + + if (slength > 0) { + get_CDR_octet_seq(tvb, seq, offset, slength); + } + + return slength; /* return length */ + +} + +/* Process a sequence of octets that represent the + * Pseudo Object Type "TypeCode". Typecodes are used for example, + * by "Any values". + * This function also increments offset to the correct position. + * + * It will parse the TypeCode and output data to the "tree" provided + * by the user + * + * It returns a guint32 representing a TCKind value. + */ + +guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, int boundary, + MessageHeader * header ) { + guint32 val; + + gint16 s_octet2; /* signed int16 */ + guint16 u_octet2; /* unsigned int16 */ + guint32 u_octet4; /* unsigned int32 */ + + val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */ + if (tree) { + proto_tree_add_uint(tree,hf_giop_TCKind,tvb, + *offset-sizeof(val),4,val); + } + + /* Grab the data according to Typecode Table - Corba Chapter 15 */ + + switch (val) { + case tk_null: /* empty parameter list */ + break; + case tk_void: /* empty parameter list */ + break; + case tk_short: /* empty parameter list */ + break; + case tk_long: /* empty parameter list */ + break; + case tk_ushort: /* empty parameter list */ + break; + case tk_ulong: /* empty parameter list */ + break; + case tk_float: /* empty parameter list */ + break; + case tk_double: /* empty parameter list */ + break; + case tk_boolean: /* empty parameter list */ + break; + case tk_char: /* empty parameter list */ + break; + case tk_octet: /* empty parameter list */ + break; + case tk_any: /* empty parameter list */ + break; + case tk_TypeCode: /* empty parameter list */ + break; + case tk_Principal: /* empty parameter list */ + break; + case tk_objref: /* complex parameter list */ + dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + case tk_struct: /* complex parameter list */ + dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + case tk_union: /* complex parameter list */ + dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + case tk_enum: /* complex parameter list */ + dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + + case tk_string: /* simple parameter list */ + u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */ + if (tree) { + proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb, + *offset-sizeof(u_octet4),4,u_octet4); + } + break; + + case tk_sequence: /* complex parameter list */ + dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + case tk_array: /* complex parameter list */ + dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + case tk_alias: /* complex parameter list */ + dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + case tk_except: /* complex parameter list */ + dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + case tk_longlong: /* empty parameter list */ + break; + case tk_ulonglong: /* empty parameter list */ + break; + case tk_longdouble: /* empty parameter list */ + break; + case tk_wchar: /* empty parameter list */ + break; + case tk_wstring: /* simple parameter list */ + u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */ + if (tree) { + proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb, + *offset-sizeof(u_octet4),4,u_octet4); + } + break; + + case tk_fixed: /* simple parameter list */ + u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */ + if (tree) { + proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb, + *offset-sizeof(u_octet2),2,u_octet2); + } + + s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */ + if (tree) { + proto_tree_add_int(tree,hf_giop_typecode_scale,tvb, + *offset-sizeof(s_octet2),2,s_octet2); + } + break; + + case tk_value: /* complex parameter list */ + dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + case tk_value_box: /* complex parameter list */ + dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + case tk_native: /* complex parameter list */ + dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + case tk_abstract_interface: /* complex parameter list */ + dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary, header ); + break; + default: + g_warning("giop: Unknown TCKind %u \n", val); + break; + } /* val */ + + return val; +} + + + +/* Copy a 4 octet sequence from the tvbuff + * which represents an unsigned long value, and convert + * it to an unsigned long vaule, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for unsigned long values. + * offset is then incremented by 4, to indicate the 4 octets which + * have been processed. + */ + +guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) { + + guint32 val; + + /* unsigned long values must be aligned on a 4 byte boundary */ + while( ( (*offset + boundary) % 4) != 0) + ++(*offset); + + val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) : + tvb_get_letohl (tvb, *offset); + + *offset += 4; + return val; +} + + /* Copy a 2 octet sequence from the tvbuff - * which represents a signed short value, and convert - * it to a signed short value, taking into account byte order. + * which represents an unsigned short value, and convert + * it to an unsigned short value, taking into account byte order. * offset is first incremented so that it falls on a proper alignment * boundary for unsigned short values. * offset is then incremented by 2, to indicate the 2 octets which * have been processed. */ -gint16 -get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian) -{ - gint16 val; +guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) { - /* short values must be aligned on a 2 byte boundary */ - while( ( (*offset + GIOP_HEADER_SIZE) % 2) != 0) + guint16 val; + + /* unsigned short values must be aligned on a 2 byte boundary */ + while( ( (*offset + boundary) % 2) != 0) ++(*offset); val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) : @@ -371,22 +2469,146 @@ get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian) -/* Copy a sequence of octets from the tvbuff. +/* Copy a wchar from the tvbuff. * Caller of this function must remember to free the * array pointed to by seq. - * This function also increments offset by len. + * This function also increments offset according to + * the wchar size. + * + * For GIOP 1.1 read 2 octets and return size -2. The + * negation means there is no size element in the packet + * and therefore no size to add to the tree. + * + * For GIOP 1.2 read size of wchar and the size + * octets. size is returned as a gint8. + * + * For both GIOP versions the wchar is returned + * as a printable string. + * */ -static void -get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, int len) -{ - *seq = g_new0(gchar, len + 1); - tvb_memcpy( tvb, *seq, *offset, len); - *offset += len; + +/* NOTE: This is very primitive in that it just reads + * the wchar as a series of octets and returns them + * to the user. No translation is attempted based on + * byte orientation, nor on code set. I.e it only + * really reads past the wchar and sets the offset + * correctly. + */ + +/* The "decoding" is done according to CORBA chapter 15. + * Wchar is not supported for GIOP 1.0. + */ + +gint8 get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) { + + gint8 slength; + gchar *raw_wstring = NULL; + + /* CORBA chapter 15: + * - prior to GIOP 1.2 wchar limited to two octet fixed length. + * - GIOP 1.2 wchar is encoded as an unsigned binary octet + * followed by the elements of the octet sequence representing + * the encoded value of the wchar. + */ + + *seq = NULL; /* set in case GIOP 1.2 length is 0 */ + slength = 2; /* set for GIOP 1.1 length in octets */ + + if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */ + slength = get_CDR_octet(tvb,offset); + + if (slength > 0) { + /* ??? assume alignment is ok for GIOP 1.1 ??? */ + get_CDR_octet_seq(tvb, &raw_wstring, offset, slength); + + /* now turn octets (wchar) into something that can be printed by the user */ + *seq = make_printable_string(raw_wstring, slength); + } + + /* if GIOP 1.1 negate length to indicate not an item to add to tree */ + if (header->GIOP_version.minor < 2) + slength = -slength; + + g_free(raw_wstring); + + return slength; /* return length */ + } + +/* Copy a wstring from the tvbuff. + * Caller of this function must remember to free the + * array pointed to by seq. + * This function also increments offset, according to + * wstring length. length is returned as guint32 + */ + +/* NOTE: This is very primitive in that it just reads + * the wstring as a series of octets and returns them + * to the user. No translation is attempted based on + * byte orientation, nor on code set. I.e it only + * really reads past the wstring and sets the offset + * correctly. + */ + +/* The "decoding" is done according to CORBA chapter 15. + * Wstring is not supported for GIOP 1.0. + */ + + +guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian, + int boundary, MessageHeader * header) { + + guint32 slength; + gchar *raw_wstring = NULL; + + /* CORBA chapter 15: + * - prior to GIOP 1.2 wstring limited to two octet fixed length. + * length and string are NUL terminated (length???). + * - GIOP 1.2 length is total number of octets. wstring is NOT NUL + * terminated. + */ + + *seq = NULL; /* set in case GIOP 1.2 length is 0 */ + + /* get length, same for all GIOP versions, + * although for 1.2 CORBA doesnt say, so assume. + */ + slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); + +#ifdef DEBUG + if (slength>200) { + fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength); + slength = 5; /* better than core dumping during debug */ + } +#endif + + if (header->GIOP_version.minor < 2) { +#if 0 + (*offset)++; /* must step past \0 delimiter */ +#endif + /* assume length is number of characters and not octets, spec not clear */ + slength = slength * 2; /* length in octets is 2 * wstring length */ + } + + if (slength > 0) { + get_CDR_octet_seq(tvb, &raw_wstring, offset, slength); + + /* now turn octets (wstring) into something that can be printed by the user */ + *seq = make_printable_string(raw_wstring, slength); + } + + g_free(raw_wstring); + + return slength; /* return length */ + +} + + + /** * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2) - * // GIOP 1.2 + * GIOP 1.2 * typedef short AddressingDisposition; * const short KeyAddr = 0; * const short ProfileAddr = 1; @@ -402,97 +2624,97 @@ get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, int len) * case ReferenceAddr: IORAddressingInfo ior; * }; */ + static void -dissect_target_address(tvbuff_t * tvb, int *offset, proto_tree * sub_tree, +dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree, MessageHeader * header, gboolean stream_is_big_endian) { guint16 discriminant; gchar *object_key = NULL; + gchar *p_object_key = NULL; guint32 len = 0; + guint32 u_octet4; - discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian); - if(sub_tree) + discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE); + if(tree) { - proto_tree_add_text (sub_tree, tvb, *offset -2, 2, + proto_tree_add_text (tree, tvb, *offset -2, 2, "TargetAddress Discriminant: %u", discriminant); } switch (discriminant) { - case 0: /* KeyAddr */ - len = get_CDR_ulong(tvb, offset, stream_is_big_endian); - get_CDR_octet_seq(tvb, &object_key, offset, len); - printable_string( object_key, len ); - - if(sub_tree) + case 0: /* KeyAddr */ + len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE); + if(tree) { - proto_tree_add_text (sub_tree, tvb, *offset -len -4, 4, + proto_tree_add_text (tree, tvb, *offset -4, 4, "KeyAddr (object key length): %u", len); - proto_tree_add_text (sub_tree, tvb, *offset -len, len, - "KeyAddr (object key): %s", object_key); } - break; - case 1: - if(sub_tree) - { - proto_tree_add_text (sub_tree, tvb, *offset, tvb_length(tvb) - *offset, - "ProfileAddr (not implemented) %s", object_key); + + if (len > 0) { + + get_CDR_octet_seq(tvb, &object_key, offset, len); + p_object_key = make_printable_string( object_key, len ); + + if(tree) + { + proto_tree_add_text (tree, tvb, *offset -len, len, + "KeyAddr (object key): %s", p_object_key); + } } break; - case 2: - if(sub_tree) + case 1: /* ProfileAddr */ + decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, + stream_is_big_endian, NULL); + break; + case 2: /* ReferenceAddr */ + u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE); + + if(tree) { - proto_tree_add_text (sub_tree, tvb, *offset, tvb_length(tvb) - *offset, - "ReferenceAddr (not implemented) %s", object_key); + proto_tree_add_text (tree, tvb, *offset -len -4, 4, + "ReferenceAddr (selected_profile_index): %u", u_octet4); } + + decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian); break; default: break; } g_free( object_key ); + g_free( p_object_key ); } static void dissect_reply_body (tvbuff_t *tvb, u_int offset, packet_info *pinfo, proto_tree *tree, gboolean stream_is_big_endian, - guint32 reply_status) -{ + guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) { + u_int sequence_length; - u_int minor_code_value; - u_int completion_status; + + gchar * repoid = NULL; /* Repositor ID looked up from objkey */ + + /* + * comp_req_list stuff + */ + + comp_req_list_entry_t * entry = NULL; /* data element in our list */ + + guint32 mfn; switch (reply_status) { case SYSTEM_EXCEPTION: - if (tree) - { - sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - - proto_tree_add_text(tree, tvb, offset-4, 4, - "Exception length: %u", sequence_length); - if (sequence_length != 0) - { - proto_tree_add_text(tree, tvb, offset, sequence_length, - "Exception id: %s", - tvb_format_text(tvb, offset, sequence_length - 1)); - offset += sequence_length; - } - - minor_code_value = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - completion_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - - proto_tree_add_text(tree, tvb, offset-8, 4, - "Minor code value: %u", minor_code_value); - proto_tree_add_text(tree, tvb, offset-4, 4, - "Completion Status: %u", completion_status); - } + decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE); break; case USER_EXCEPTION: + if (tree) { - sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); proto_tree_add_text(tree, tvb, offset-4, 4, "Exception length: %u", sequence_length); @@ -503,35 +2725,118 @@ dissect_reply_body (tvbuff_t *tvb, u_int offset, packet_info *pinfo, "Exception id: %s", tvb_format_text(tvb, offset, sequence_length)); +#if 1 + + header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */ + + /* read exception id from buffer and store in*/ + + tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id ); + + +#endif + + offset += sequence_length; } - sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - proto_tree_add_text(tree, tvb, offset-4, 4, - "Exception member length: %u", sequence_length); - if (sequence_length != 0) - { - proto_tree_add_text(tree, tvb, offset, sequence_length, - "Exception member: %s", - tvb_format_text(tvb, offset, sequence_length - 1)); - } + } /* tree */ + + + /* + * Now just fall through to the NO_EXCEPTION part + * as this is common . + */ + + + + case NO_EXCEPTION: + + + /* lookup MFN in hash directly */ + + mfn = get_mfn_from_fn(pinfo->fd->num); + + if (mfn == pinfo->fd->num) + return; /* no matching frame number, what am I */ + + /* get entry for this MFN */ + entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */ + + if (!entry) + return; /* no matching entry */ + + + /* + * If this packet is a REPLY to a RESOLVE(request) + * then decode IOR. + * TODO - make this lookup faster -- FS + */ + + if (!strcmp(giop_op_resolve,entry->operation)) { + decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian); + return; /* done */ + } + + /* TODO -- Put stuff here for other "interesting operations" */ + + /* + * + * Call sub dissector. + * First try an find a explicit sub_dissector, then if that + * fails, try the heuristic method. + */ + +#if DEBUG_CALL_SUB_DISSECTORS + + if(entry->repoid) { + try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid ); + break; + + } else { + try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation); + } /* repoid */ + + +#endif + break; + + case LOCATION_FORWARD: + g_warning("giop: We don't yet dissect LOCATION_FORWARD\n"); + + break; + + case LOCATION_FORWARD_PERM: + g_warning("giop: We don't yet dissect LOCATION_FORWARD_PERM\n"); + + break; + + case NEEDS_ADDRESSING_MODE: + g_warning("giop: We don't yet dissect NEEDS_ADDRESSING_MODE\n"); - } break; default: - if (tree) - { - proto_tree_add_text(tree, tvb, offset, - tvb_length_remaining(tvb, offset), - "Reply body: <not shown>"); - } - } + + g_warning("giop: UNKNOWN_EXCEPTION %i request_id = %u\n",reply_status, header->req_id); + + break; + + } /* switch */ + + g_free(repoid); /* free resource */ + + return; /* done */ + } + + + + /* The format of the Reply Header for GIOP 1.0 and 1.1 - * is documented in Section 15.4.3.1 * of the CORBA 2.4 standard. + * is documented in Section 15.4.3.1 of the CORBA 2.4 standard. struct ReplyHeader_1_0 { IOP::ServiceContextList service_context; @@ -539,126 +2844,79 @@ dissect_reply_body (tvbuff_t *tvb, u_int offset, packet_info *pinfo, ReplyStatusType_1_0 reply_status; }; */ -static void -dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, - proto_tree * clnp_tree, MessageHeader * header, - gboolean stream_is_big_endian) -{ + +static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, + proto_tree * clnp_tree, MessageHeader * header, + gboolean stream_is_big_endian) { + guint32 offset = 0; - guint32 nr_seq = 0; - guint32 context_id; - guint32 sequence_length; guint32 request_id; guint32 reply_status; - gboolean big_endian; proto_tree *reply_tree = NULL; proto_item *tf; + guint32 mfn; /* matching frame number */ - guint32 i; - - big_endian = is_big_endian (header); - - /* From Section 15.3.2.5 of the CORBA 2.4 standard, a sequence - * is an unsigned long value (4 octets) indicating the number of - * items in the sequence, followed by the items in the sequence - */ - - /* The format of the IOP::ServiceContextList struct is defined in - * section 13.7 of the CORBA 2.4 standard as: - module IOP { // IDL - typedef unsigned long ServiceId; - - struct ServiceContext { - ServiceId context_id; - sequence <octet> context_data; - }; - typedef sequence <ServiceContext>ServiceContextList; - }; + if (tree) { + tf = proto_tree_add_text (tree, tvb, offset, + tvb_length (tvb), + "General Inter-ORB Protocol Reply"); + if (reply_tree == NULL) + { + reply_tree = proto_item_add_subtree (tf, ett_giop_reply); + + } + } + + /* + * Decode IOP::ServiceContextList */ - if (tree) - { - tf = proto_tree_add_text (tree, tvb, offset, - tvb_length (tvb), - "General Inter-ORB Protocol Reply"); - if (reply_tree == NULL) - { - reply_tree = proto_item_add_subtree (tf, ett_giop_reply); - - } - } - - nr_seq = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - - for (i = 1; i <= nr_seq; i++) - { + + decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE); - if (big_endian) - { - context_id = tvb_get_ntohl (tvb, offset); - sequence_length = tvb_get_ntohl (tvb, offset + 4); - } - else - { - context_id = tvb_get_letohl (tvb, offset); - sequence_length = tvb_get_letohl (tvb, offset + 4); - } + request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); - context_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + if (check_col(pinfo->fd, COL_INFO)) { + col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id); + } - if (tree) - { - proto_tree_add_text (reply_tree, tvb, offset -4, 4, - "Context id: %u", context_id); - } + if (tree) { + proto_tree_add_text (reply_tree, tvb, offset-4, 4, + "Request id: %u", request_id); + } - sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - if(tree) - { - proto_tree_add_text (reply_tree, tvb, offset -4, - 4, "Sequence length: %u", sequence_length); - } + reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); - if(tree) - { - if (sequence_length > 0) - { - proto_tree_add_text (reply_tree, tvb, offset, - sequence_length, - "Sequence data: <not shown>"); - } - } + if (check_col(pinfo->fd, COL_INFO)) { + col_append_fstr(pinfo->fd, COL_INFO, ": %s", + val_to_str(reply_status, reply_status_types, "Unknown (%u)")); - offset += sequence_length; + } - } /* for */ + if (tree) { + proto_tree_add_text (reply_tree, tvb, offset-4, 4, + "Reply status: %s", + val_to_str(reply_status, reply_status_types, "Unknown (%u)")); + + } - request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - if (check_col(pinfo->fd, COL_INFO)) - { - col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id); - } - if (tree) - { - proto_tree_add_text (reply_tree, tvb, offset-4, 4, - "Request id: %u", request_id); - } + /* + * Save FN and MFN in complete_reply_hash, only if user is NOT clicking + */ - reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - if (check_col(pinfo->fd, COL_INFO)) - { - col_append_fstr(pinfo->fd, COL_INFO, ": %s", - val_to_str(reply_status, reply_status_types, "Unknown (%u)")); + if (! pinfo->fd->flags.visited) { + mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */ + if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */ + insert_in_complete_reply_hash(pinfo->fd->num, mfn); } - if (tree) - { - proto_tree_add_text (reply_tree, tvb, offset-4, 4, - "Reply status: %s", - val_to_str(reply_status, reply_status_types, "Unknown (%u)")); + } - } + header->req_id = request_id; /* save for sub dissector */ + header->rep_status = reply_status; /* save for sub dissector */ dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian, - reply_status); + reply_status, header,tree); + + } /** The format of the GIOP 1.2 Reply header is very similar to the 1.0 @@ -666,134 +2924,122 @@ dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, * 15.4.3.1 of the CORBA 2.4 specification: * * struct ReplyHeader_1_2 { - unsigned long request_id; - ReplyStatusType_1_2 reply_status; - IOP:ServiceContextList service_context; // 1.2 change - }; + * unsigned long request_id; + * ReplyStatusType_1_2 reply_status; + * IOP:ServiceContextList service_context; + * }; */ -static void -dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo, - proto_tree * tree, proto_tree * clnp_tree, - MessageHeader * header, - gboolean stream_is_big_endian) -{ + +static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo, + proto_tree * tree, proto_tree * clnp_tree, + MessageHeader * header, + gboolean stream_is_big_endian) { + u_int offset = 0; - guint32 nr_seq = 0; - guint32 context_id; - guint32 sequence_length; guint32 request_id; guint32 reply_status; proto_tree *reply_tree = NULL; proto_item *tf; - guint32 i; + guint32 mfn; /* matching frame number */ + + if (tree) { + tf = proto_tree_add_text (tree, tvb, offset, + tvb_length (tvb), + "General Inter-ORB Protocol Reply"); + reply_tree = proto_item_add_subtree (tf, ett_giop_reply); + } + + request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); + + if (check_col(pinfo->fd, COL_INFO)) { + col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id); + } - if (tree) - { - tf = proto_tree_add_text (tree, tvb, offset, - tvb_length (tvb), - "General Inter-ORB Protocol Reply"); - if (reply_tree == NULL) - { - reply_tree = proto_item_add_subtree (tf, ett_giop_reply); + if (tree) { + proto_tree_add_text (reply_tree, tvb, offset-4, 4, + "Request id: %u", request_id); + } - } - } + reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); + + if (check_col(pinfo->fd, COL_INFO)) { + col_append_fstr(pinfo->fd, COL_INFO, ": %s", + val_to_str(reply_status, reply_status_types, "Unknown (%u)")); - request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - if (check_col(pinfo->fd, COL_INFO)) - { - col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id); - } - if (tree) - { - proto_tree_add_text (reply_tree, tvb, offset-4, 4, - "Request id: %u", request_id); - } + } - reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - if (check_col(pinfo->fd, COL_INFO)) - { - col_append_fstr(pinfo->fd, COL_INFO, ": %s", - val_to_str(reply_status, reply_status_types, "Unknown (%u)")); - } - if (tree) - { - proto_tree_add_text (reply_tree, tvb, offset-4, 4, - "Reply status: %s", - val_to_str(reply_status, reply_status_types, "Unknown (%u)")); + if (tree) { + proto_tree_add_text (reply_tree, tvb, offset-4, 4, + "Reply status: %s", + val_to_str(reply_status, reply_status_types, "Unknown (%u)")); - } + } - nr_seq = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + /* + * Decode IOP::ServiceContextList + */ - for (i = 1; i <= nr_seq; i++) - { + decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE); - context_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - if (tree) - { - proto_tree_add_text (reply_tree, tvb, offset -4, 4, - "Context id: %u", context_id); - } + /* + * GIOP 1.2 Reply body must fall on an 8 octet alignment. + */ - sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - if (tree) - { - proto_tree_add_text (reply_tree, tvb, offset- 4, - 4, "Sequence length: %u", sequence_length); - } + set_new_alignment(&offset, GIOP_HEADER_SIZE, 8); - offset += sequence_length; - if (tree) - { - if (sequence_length > 0) - { - proto_tree_add_text (reply_tree, tvb, offset - sequence_length, - sequence_length, - "Sequence data: <not shown>"); - } - } + /* + * Save FN and MFN in complete_reply_hash, only if user is NOT clicking + */ + + if (! pinfo->fd->flags.visited) { + mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */ + if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */ + insert_in_complete_reply_hash(pinfo->fd->num, mfn); + } + } + + /* + * Add header to argument list so sub dissector can get header info. + */ - } /* for */ + header->req_id = request_id; /* save for sub dissector */ + header->rep_status = reply_status; /* save for sub dissector */ dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian, - reply_status); + reply_status,header,tree); + } -static void -dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo, + + +static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, proto_tree * clnp_tree, - MessageHeader * header, gboolean stream_is_big_endian) -{ + MessageHeader * header, gboolean stream_is_big_endian) { + u_int offset = 0; guint32 request_id; proto_tree *cancel_request_tree = NULL; proto_item *tf; - if (tree) - { - tf = proto_tree_add_text (tree, tvb, offset, - tvb_length (tvb), - "General Inter-ORB Protocol CancelRequest"); - if (cancel_request_tree == NULL) - { - cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request); - - } - } + if (tree) { + tf = proto_tree_add_text (tree, tvb, offset, + tvb_length (tvb), + "General Inter-ORB Protocol CancelRequest"); + cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request); + } - request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - if (check_col(pinfo->fd, COL_INFO)) - { - col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id); - } - if (tree) - { - proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4, - "Request id: %u", request_id); - } + request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); + + if (check_col(pinfo->fd, COL_INFO)) { + col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id); + } + if (tree) { + proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4, + "Request id: %u", request_id); + } + } /** The formats for GIOP 1.0 and 1.1 Request messages are defined @@ -815,19 +3061,22 @@ dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo, MessageHeader * header, gboolean stream_is_big_endian) { guint32 offset = 0; - guint32 nr_seq = 0; - guint32 context_id; - guint32 sequence_length; guint32 request_id; guint32 len = 0; - gchar *object_key = NULL; + + guint32 objkey_len = 0; /* object key length */ + gchar *objkey = NULL; /* object key sequence */ + gchar *print_objkey = NULL; /* printable object key sequence */ + gchar *operation = NULL; gchar *requesting_principal = NULL; + gchar *print_requesting_principal = NULL; guint8 response_expected; gchar *reserved = NULL; proto_tree *request_tree = NULL; proto_item *tf; - guint32 i; + + gchar *repoid = NULL; /* from object key lookup in objkey hash */ if (tree) @@ -842,37 +3091,17 @@ dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo, } } - nr_seq = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - for (i = 1; i <= nr_seq; i++) - { - context_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - if (tree) - { - proto_tree_add_text (request_tree, tvb, offset-4, 4, - "Context id: %u", context_id); - } - - sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - if(tree) - { - proto_tree_add_text (request_tree, tvb, offset-4, 4, - "Sequence length: %u", sequence_length); - } - offset += sequence_length; - if (sequence_length > 0) - { - proto_tree_add_text (request_tree, tvb, offset - sequence_length, - sequence_length, - "Sequence data: <not shown>"); - } - + /* + * Decode IOP::ServiceContextList + */ + + decode_ServiceContextList(tvb, pinfo, request_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE); - } /* for */ - request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); if (check_col(pinfo->fd, COL_INFO)) { col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id); @@ -906,39 +3135,42 @@ dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo, } } + + /* Length of object_key sequence */ - len = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); + if(tree) { proto_tree_add_text (request_tree, tvb, offset-4, 4, - /**/ "Object Key length: %u", len); + /**/ "Object Key length: %u", objkey_len); } - if( len > 0) + if (objkey_len > 0) { - get_CDR_octet_seq(tvb, &object_key, &offset, len); - printable_string( object_key, len ); + get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len); + + print_objkey = make_printable_string(objkey, objkey_len); if(tree) { - proto_tree_add_text (request_tree, tvb, offset - len, len, - /**/ "Object Key: %s", object_key); + proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len, + /**/ "Object Key: %s", print_objkey); } } - /* length of operation string */ - len = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + /* length of operation string and string */ + len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); if(tree) { - proto_tree_add_text (request_tree, tvb, offset -4, 4, + proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4, /**/ "Operation length: %u", len); } if( len > 0) { - get_CDR_octet_seq(tvb, &operation, &offset, len); if (check_col(pinfo->fd, COL_INFO)) { col_append_fstr(pinfo->fd, COL_INFO, ": %s", operation); @@ -952,7 +3184,7 @@ dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo, } /* length of requesting_principal string */ - len = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); if(tree) { proto_tree_add_text (request_tree, tvb, offset-4, 4, @@ -962,17 +3194,56 @@ dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo, if( len > 0) { get_CDR_octet_seq(tvb, &requesting_principal, &offset, len); + + print_requesting_principal = make_printable_string(requesting_principal, len); + if(tree) { proto_tree_add_text (request_tree, tvb, offset - len, len, - /**/ "Requesting Principal: %s", requesting_principal); + /**/ "Requesting Principal: %s", print_requesting_principal); } } - g_free( object_key ); + + /* + * Save FN,reqid,and operation for later. Add sub_handle later. + * But only if user is NOT clicking. + */ + + if (! pinfo->fd->flags.visited) + giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num, + request_id,operation,NULL); + + + /* + * Call subdissector here before freeing "operation" and "key" + * pass request_id also. But only if anything remains in tvbuff. + * First try an find an explicit sub_dissector, then if that + * fails, try the heuristic method. + * + */ + + + header->req_id = request_id; /* save for sub dissector */ + repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len); + +#if DEBUG_CALL_SUB_DISSECTORS + + if(repoid) { + try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid); + } else { + try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation); + } + +#endif + + g_free( print_objkey ); + g_free( objkey ); g_free( operation ); g_free( requesting_principal ); + g_free( print_requesting_principal ); + } /** The format of a GIOP 1.2 RequestHeader message is @@ -1002,19 +3273,18 @@ dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo, proto_tree *request_tree = NULL; proto_item *tf; + gchar *repoid = NULL; + + if (tree) { tf = proto_tree_add_text (tree, tvb, offset, tvb_length (tvb), "General Inter-ORB Protocol Request"); - if (request_tree == NULL) - { - request_tree = proto_item_add_subtree (tf, ett_giop_reply); - - } + request_tree = proto_item_add_subtree (tf, ett_giop_reply); } - request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); if (check_col(pinfo->fd, COL_INFO)) { col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id); @@ -1042,19 +3312,18 @@ dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo, "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]); } - dissect_target_address(tvb, &offset, request_tree, header, stream_is_big_endian); + dissect_target_address(tvb, pinfo, &offset, request_tree, header, stream_is_big_endian); /* length of operation string */ - len = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); if(tree) { - proto_tree_add_text (request_tree, tvb, offset -4, 4, + proto_tree_add_text (request_tree, tvb, offset - len - 4, 4, /**/ "Operation length: %u", len); } if( len > 0) { - get_CDR_octet_seq(tvb, &operation, &offset, len); if (check_col(pinfo->fd, COL_INFO)) { col_append_fstr(pinfo->fd, COL_INFO, ": %s", operation); @@ -1067,6 +3336,42 @@ dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo, } } + + /* + * Decode IOP::ServiceContextList + */ + + decode_ServiceContextList(tvb, pinfo, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE); + + /* + * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into + * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the + * GIOP octet stream start. + */ + + set_new_alignment(&offset, GIOP_HEADER_SIZE, 8); + + /* + * Save FN,reqid,and operation for later. Add sub_handle later. + * But only if user is NOT clicking. + */ + + if (! pinfo->fd->flags.visited) + giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num, + request_id,operation,NULL); + +#if DEBUG_CALL_SUB_DISSECTORS + + if(repoid) { + try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid); + } else { + try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation); + } + + +#endif + + g_free(operation); g_free(reserved); } @@ -1079,6 +3384,7 @@ dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo, guint32 request_id; guint32 len = 0; gchar *object_key = NULL; + gchar *p_object_key = NULL; proto_tree *locate_request_tree = NULL; proto_item *tf; @@ -1094,7 +3400,7 @@ dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo, } } - request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); if (check_col(pinfo->fd, COL_INFO)) { col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id); @@ -1107,26 +3413,34 @@ dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo, if(header->GIOP_version.minor < 2) { - len = get_CDR_ulong(tvb, &offset, stream_is_big_endian); - get_CDR_octet_seq(tvb, &object_key, &offset, len); - - if(locate_request_tree) - { + len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); + if (locate_request_tree) + { + proto_tree_add_text (locate_request_tree, tvb, offset-4, 4, + "Object Key length: %u", len); + } - proto_tree_add_text (locate_request_tree, tvb, offset-len, len, - "Object Key: %s", object_key); + if (len > 0) { + get_CDR_octet_seq(tvb, &object_key, &offset, len); + p_object_key = make_printable_string(object_key, len); + + if(locate_request_tree) + { + proto_tree_add_text (locate_request_tree, tvb, offset-len, len, + "Object Key: %s", p_object_key); + } } - } else /* GIOP 1.2 and higher */ { - dissect_target_address(tvb, &offset, locate_request_tree, header, + dissect_target_address(tvb, pinfo, &offset, locate_request_tree, header, stream_is_big_endian); } - g_free( object_key ); + g_free(object_key); + g_free(p_object_key); } static void @@ -1137,6 +3451,8 @@ dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo, guint32 offset = 0; guint32 request_id; guint32 locate_status; + guint16 addr_disp; + proto_tree *locate_reply_tree = NULL; proto_item *tf; @@ -1152,7 +3468,7 @@ dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo, } } - request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); if (check_col(pinfo->fd, COL_INFO)) { col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id); @@ -1163,16 +3479,46 @@ dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo, "Request id: %u", request_id); } - locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); if (locate_reply_tree) { proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4, "Locate status: %s", match_strval(locate_status, giop_locate_status_types) ); - } + /* Decode the LocateReply body. + * + * For GIOP 1.0 and 1.1 body immediately follows header. + * For GIOP 1.2 it is aligned on 8 octet boundary so need to + * spin up. + */ + + if (header->GIOP_version.minor > 1) { + while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0) + ++(offset); + } + + switch(locate_status) { + case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */ + case OBJECT_FORWARD_PERM: + decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian); + break; + case LOC_SYSTEM_EXCEPTION: + decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE); + break; + case LOC_NEEDS_ADDRESSING_MODE: + addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); + if(locate_reply_tree) { + proto_tree_add_text (tree, tvb, offset -2, 2, + "AddressingDisposition: %u", addr_disp); + } + break; + default: /* others have no reply body */ + break; + } + } static void @@ -1196,7 +3542,7 @@ dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, } } - request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian); + request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE); if (check_col(pinfo->fd, COL_INFO)) { col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id); @@ -1206,15 +3552,13 @@ dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, proto_tree_add_text (fragment_tree, tvb, offset-4, 4, "Request id: %u", request_id); } - } -/* main entry point */ -static gboolean -dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) -{ +/* Main entry point */ + +gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) { u_int offset = 0; MessageHeader header; tvbuff_t *giop_header_tvb; @@ -1226,6 +3570,18 @@ dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) u_int minor_version; gboolean stream_is_big_endian; + + /* DEBUG */ + +#if DEBUG + giop_dump_collection(cd_module_hash); + giop_dump_collection(cd_objkey_hash); + giop_dump_collection(cd_heuristic_users); + giop_dump_collection(cd_complete_reply_hash); + giop_dump_collection(cd_complete_request_list); +#endif + + /* check magic number and version */ @@ -1240,13 +3596,18 @@ dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1); payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1); + + /* + * because I have added extra elements in MessageHeader struct + * for sub dissectors. -- FS + */ - /* memcpy(&header, &pd[offset], sizeof(header)); */ - tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, sizeof (header)); + tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE ); if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0) { /* Not a GIOP message. */ + return FALSE; } @@ -1262,9 +3623,10 @@ dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) as data, or should we return FALSE on the theory that it might have been some other packet that happened to begin with "GIOP"? We shouldn't do *both*, so we return TRUE, for now. - If we should return FALSE, we should do so *without* setting - the "Info" column, *without* setting the "Protocol" column, - and *without* adding anything to the protocol tree. */ + If we should return FALSE, we should do so *without* setting + the "Info" column, *without* setting the "Protocol" column, + and *without* adding anything to the protocol tree. */ + if (check_col (pinfo->fd, COL_INFO)) { col_add_fstr (pinfo->fd, COL_INFO, "Version %u.%u", @@ -1341,6 +3703,15 @@ dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) } /* tree */ +#if 0 + if (check_col (pinfo->fd, COL_INFO)) + { + col_add_fstr (pinfo->fd, COL_INFO, "GIOP %u.%u %s", + header.GIOP_version.major, header.GIOP_version.minor, + match_strval(header.message_type, giop_message_types)); + } +#endif + switch (header.message_type) { @@ -1391,6 +3762,10 @@ dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) break; } /* switch message_type */ + + + + return TRUE; } @@ -1398,21 +3773,219 @@ void proto_register_giop (void) { static hf_register_info hf[] = { - { - &hf_giop_message_type, - { - "Message type", "giop.type", - FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } - } + { &hf_giop_message_type, + { "Message type", "giop.type", + FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_message_size, + { "Message size", "giop.len", + FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_repoid, + { "Repository ID", "giop.repoid", + FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_string_length, + { "String Length", "giop.strlen", + FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_sequence_length, + { "Sequence Length", "giop.seqlen", + FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_profile_id, + { "Profile ID", "giop.profid", + FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL } + }, + + + { &hf_giop_type_id, + { "IOR::type_id", "giop.typeid", + FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_iiop_v_maj, + { "IIOP Major Version", "giop.iiop_vmaj", + FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } + } , - { - &hf_giop_message_size, - { - "Message size", "giop.len", - FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } - } + { &hf_giop_iiop_v_min, + { "IIOP Minor Version", "giop.iiop_vmin", + FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_endianess, + { "Endianess", "giop.endianess", + FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL } + }, + + { &hf_giop_IIOP_tag, + { "IIOP Component TAG", "giop.iioptag", + FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_IOR_tag, + { "IOR Profile TAG", "giop.iortag", + FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_TCKind, + { "TypeCode enum", "giop.TCKind", + FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL } + }, + + { &hf_giop_typecode_count, + { "TypeCode count", "giop.tccount", + FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_typecode_default_used, + { "default_used", "giop.tcdefault_used", + FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_typecode_digits, + { "Digits", "giop.tcdigits", + FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + + { &hf_giop_typecode_length, + { "Length", "giop.tclength", + FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_typecode_max_length, + { "Maximum length", "giop.tcmaxlen", + FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_typecode_member_name, + { "TypeCode member name", "giop.tcmemname", + FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_typecode_name, + { "TypeCode name", "giop.tcname", + FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_typecode_scale, + { "Scale", "giop.tcscale", + FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_typecode_ValueModifier, + { "ValueModifier", "giop.tcValueModifier", + FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_typecode_Visibility, + { "Visibility", "giop.tcVisibility", + FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + + + { &hf_giop_type_boolean, + { "TypeCode boolean data", "giop.tcboolean", + FT_BOOLEAN, BASE_DEC, NULL, 0x0, "" } + }, + + { &hf_giop_type_char, + { "TypeCode char data", "giop.tcchar", + FT_UINT8, BASE_DEC, NULL, 0x0, "" } + }, + + { &hf_giop_type_double, + { "TypeCode double data", "giop.tcdouble", + FT_DOUBLE, BASE_DEC, NULL, 0x0, "" } + }, + + { &hf_giop_type_enum, + { "TypeCode enum data", "giop.tcenumdata", + FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + /* + * float as double ?? -- FIX + */ + + { &hf_giop_type_float, + { "TypeCode float data", "giop.tcfloat", + FT_DOUBLE, BASE_DEC, NULL, 0x0, "" } + }, + + { &hf_giop_type_long, + { "TypeCode long data", "giop.tclongdata", + FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_type_octet, + { "TypeCode octet data", "giop.tcoctet", + FT_UINT8, BASE_DEC, NULL, 0x0, "" } + }, + + { &hf_giop_type_short, + { "TypeCode short data", "giop.tcshortdata", + FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_type_string, + { "TypeCode string data", "giop.tcstring", + FT_STRING, BASE_DEC, NULL, 0x0, "" } + }, + + { &hf_giop_type_ulong, + { "TypeCode ulong data", "giop.tculongdata", + FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + { &hf_giop_type_ushort, + { "TypeCode ushort data", "giop.tcushortdata", + FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } + }, + + /* + * IIOP Module - Chapter 15.10.2 + */ + + { &hf_giop_iiop_host, + { "IIOP::Profile_host", "giop.iiop.host", + FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL } + } + , + + { &hf_giop_iiop_port, + { "IIOP::Profile_port", "giop.iiop.port", + FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } + } + , + + /* + * IIOP ServiceContext + */ + + { &hf_giop_iop_vscid, + { "VSCID", "giop.iiop.vscid", + FT_UINT32, BASE_HEX, NULL, 0xfffff000, "", HFILL } + } + , + + { &hf_giop_iop_scid, + { "SCID", "giop.iiop.scid", + FT_UINT32, BASE_HEX, NULL, 0x00000fff, "", HFILL } + } , + + }; + static gint *ett[] = { &ett_giop, &ett_giop_reply, @@ -1426,10 +3999,1303 @@ proto_register_giop (void) "giop"); proto_register_field_array (proto_giop, hf, array_length (hf)); proto_register_subtree_array (ett, array_length (ett)); + + + /* register init routine */ + + register_init_routine( &giop_init); /* any init stuff */ + + /* + * Init the giop user module hash tables here, as giop users + * will populate it via register_giop_user_module BEFORE my + * own giop_init() is called. + */ + + giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal); + + giop_module_keys = g_mem_chunk_new("giop_module_keys", + sizeof(struct giop_module_key), + giop_module_init_count * sizeof(struct giop_module_key), + G_ALLOC_AND_FREE); + + giop_module_vals = g_mem_chunk_new("giop_module_vals", + sizeof(struct giop_module_val), + giop_module_init_count * sizeof(struct giop_module_val), + G_ALLOC_AND_FREE); + } -void -proto_reg_handoff_giop (void) -{ - heur_dissector_add ("tcp", dissect_giop, proto_giop); + + +void proto_reg_handoff_giop (void) { + heur_dissector_add("tcp", dissect_giop, proto_giop); +} + + + + +/* + * Decode IOR + * + * Ref Corba v2.4.2 Chapter 13 + * + */ + +/* + +module IOP{ + + typedef unsigned long ProfileId; + + const ProfileId TAG_INTERNET_IOP = 0; + const ProfileId TAG_MULTIPLE_COMPONENTS = 1; + + struct TaggedProfile { + ProfileId tag; + sequence <octet> profile_data; + }; + + struct IOR { + string type_id; + sequence <TaggedProfile> profiles; + }; + + typedef unsigned long ComponentId; + + struct TaggedComponent { + ComponentId tag; + sequence <octet> component_data; + }; + + typedef sequence <TaggedComponent> MultipleComponentProfile; + +}; + +*/ + +void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + guint32 boundary, gboolean stream_is_big_endian) { + + + guint32 seqlen_p; /* sequence length of profiles */ + guint32 u_octet4; + + gchar *repobuf = NULL; /* for repository ID */ + + int i; + + /* Get type_id == Repository ID */ + + u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary); + + if (tree) { + proto_tree_add_uint(tree,hf_giop_string_length,tvb, + *offset-u_octet4-sizeof(u_octet4),4,u_octet4); + if (u_octet4 > 0) { + proto_tree_add_string(tree,hf_giop_type_id,tvb, + *offset-u_octet4,u_octet4,repobuf); + } + } + + + /* g_free(repobuf); */ /* dont free yet, as must wait until I have */ + /* the object key before I can add both to hash */ + /* this is done later */ + + /* Now get a sequence of profiles */ + /* Get sequence length (number of elements) */ + + seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_sequence_length,tvb, + *offset-sizeof(seqlen_p),4,seqlen_p); + } + + + /* fetch all TaggedProfiles in this sequence */ + + for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */ + decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf); + } + +} + +static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) { + + guint32 seqlen_pd; /* sequence length of profile data */ + + guint32 pidtag; /* profile ID TAG */ + + gchar *profile_data = NULL; /* profile_data pointer */ + gchar *p_profile_data = NULL; /* printable profile_data pointer */ + + guint32 new_boundary; /* for encapsulations encountered */ + gboolean new_big_endianess; /* for encapsulations encountered */ + + /* Get ProfileId tag */ + + pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); + + if (tree) { + proto_tree_add_uint(tree,hf_giop_profile_id,tvb, + *offset-sizeof(pidtag),4,pidtag); + } + + /* get sequence length, new endianness and boundary for encapsulation */ + + seqlen_pd = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_big_endianess, &new_boundary); + + /* return if zero length sequence */ + + if(seqlen_pd == 0) + return; + + + /* + * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then + * decode it, otherwise just dump the octet sequence + * + * also, store IOR in our objectkey hash + * + * TODO - handle other TAGS + */ + + switch(pidtag) { + case IOP_TAG_INTERNET_IOP: + + decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE); + break; + + default: + + /* fetch all octets in this sequence */ + + get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd); + + /* Make a printable string */ + + p_profile_data = make_printable_string( profile_data, seqlen_pd ); + + if(tree) { + proto_tree_add_text (tree, tvb, *offset -seqlen_pd, seqlen_pd, + "Profile Data: %s", p_profile_data); + } + + break; + + } + g_free(profile_data); + g_free(p_profile_data); + +} + + + +/* + * Decode IIOP IOR Profile + * Ref Chap 15.7.2 in Corba Spec + */ + + +static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf, + gboolean store_flag) { + + int i; /* loop index */ + + guint8 v_major,v_minor; /* IIOP sersion */ + gchar *buf = NULL; + guint32 u_octet4; /* u long */ + guint16 u_octet2; /* u short */ + guint32 seqlen; /* generic sequence length */ + guint32 seqlen1; /* generic sequence length */ + gchar *objkey = NULL; /* object key pointer */ + gchar *p_chars = NULL; /* printable characters pointer */ + + + /* Get major/minor version */ + + v_major = get_CDR_octet(tvb,offset); + v_minor = get_CDR_octet(tvb,offset); + + + if (tree) { + proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb, + *offset-sizeof(v_minor)-sizeof(v_major),1,v_major ); + proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb, + *offset-sizeof(v_minor),1,v_minor ); + } + + + /* host */ + + u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary); + + if (tree) { + proto_tree_add_uint(tree,hf_giop_string_length,tvb, + *offset-u_octet4-sizeof(u_octet4),4,u_octet4); + if (u_octet4 > 0) { + proto_tree_add_string(tree,hf_giop_iiop_host,tvb, + *offset-u_octet4,u_octet4,buf); + } + } + + g_free(buf); /* dont forget */ + + /* Port */ + + u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); + + if (tree) { + proto_tree_add_uint(tree,hf_giop_iiop_port,tvb, + *offset-sizeof(u_octet2),2,u_octet2); + } + + + /* Object Key - sequence<octet> object_key */ + + seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); + + if (tree) { + proto_tree_add_uint(tree,hf_giop_sequence_length,tvb, + *offset-sizeof(seqlen),4,seqlen); + } + + if (seqlen > 0) { + /* fetch all octets in this sequence */ + get_CDR_octet_seq(tvb, &objkey, offset, seqlen); + + /* + * Now we may have the Repository ID from earlier, as well + * as the object key sequence and lengh. So lets store them in + * our objectkey hash and free buffers. + * + * But only insert if user is not clicking and repo id not NULL. + * + */ + + if (repo_id_buf) { + if (pinfo) { + if(!pinfo->fd->flags.visited) + insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res); + } + else { + + /* + * No pinfo, but store anyway if flag set. eg: IOR read from file + */ + + if (store_flag) + insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file); + } + } + + /* Make a printable string */ + + p_chars = make_printable_string( objkey, seqlen ); + + if(tree) { + proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen, + "Object Key: %s", p_chars); + } + } + + g_free(repo_id_buf); + g_free(objkey); + g_free(p_chars); + p_chars = NULL; /* reuse later */ + + /* + * Now see if if its v1.1 or 1.2, as they can contain + * extra sequence of IOP::TaggedComponents + * + */ + + switch(v_minor) { + case 0: + + /* nothing extra */ + break; + + case 1: + case 2: + + /* sequence of IOP::TaggedComponents */ + /* Ref Chap 13 in Corba Spec */ + + /* get sequence length */ + seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); + + if (tree) { + proto_tree_add_uint(tree,hf_giop_sequence_length,tvb, + *offset-sizeof(seqlen),4,seqlen); + } + + for (i=0; i< seqlen; i++) { + /* get tag */ + u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb, + *offset-sizeof(u_octet4),4,u_octet4); + } + + /* get component_data */ + seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_sequence_length,tvb, + *offset-sizeof(seqlen1),4,seqlen1); + } + + if (seqlen1 > 0) { + get_CDR_octet_seq(tvb, &buf, offset, seqlen1); + + if (tree) { + /* Make a printable string of data */ + + p_chars = make_printable_string(buf, seqlen1); + + proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1, + "component_data: %s", p_chars); + + } + } + + g_free(buf); + g_free(p_chars); + buf = NULL; /* reuse later */ + p_chars = NULL; /* reuse later */ + + } + + + break; + + default: + g_warning("giop:Invalid v_minor value = %u ", v_minor); + break; + } + +} + + +/* + * Service Contexts Begin + * + */ + + + + + +void dissect_SID_BI_DIR_IIOP(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + MessageHeader *header, gchar *operation, guint32 boundary) { + + return; + +}; + + + + +/* + * Service Contexts End + * + */ + + + + +/* + * Corba , chp 13.7 + * + * + * + * typedef unsigned long ServiceID; + * + * struct ServiceContext { + * ServiceID context_id; + * sequence <octet> context_data; + * }; + * typedef sequence <ServiceContext> ServiceContextList; + * + * + * Note: Spec says context_data is an encapsulation. + * + * + */ + + + +void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + gboolean stream_is_be, guint32 boundary) { + + guint32 seqlen; /* sequence length */ + guint32 seqlen_cd; /* sequence length, context_data */ + + guint32 context_id; + gchar *context_data = NULL; + gchar *p_context_data = NULL; + + int i; + guint32 vscid; /* Vendor Service context id */ + guint32 scid; + + + /* Get sequence length (number of elements) */ + + seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_sequence_length,tvb, + *offset-sizeof(seqlen),4,seqlen); + } + + /* return if zero length sequence */ + + if(seqlen == 0) + return; + + /* Loop for all ServiceContext's */ + + for (i=0; i<seqlen; i++) { + + context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb, + *offset-sizeof(context_id),4,context_id); + + proto_tree_add_uint(tree,hf_giop_iop_scid,tvb, + *offset-sizeof(context_id),4,context_id); + + } + + vscid = context_id && 0xfffff000; /* vendor info, top 20 bits */ + scid = context_id && 0x00000fff; /* standard service info, lower 12 bits */ + + +#if CONTEXT_DATA_IS_ENCAPSULATED + + /* get sequence length, new endianness and boundary for encapsulation */ + + seqlen_cd = get_CDR_encap_info(tvb, tree, offset, + stream_is_be, boundary, + &new_big_endianess, &new_boundary); + + +#else + /* get sequence length, and NO encapsulation */ + + seqlen_cd = get_CDR_ulong(tvb, offset, stream_is_be,boundary); + +#endif + + /* return if zero length sequence */ + + if(seqlen_cd == 0) + return; + + /* + * Now decode sequence according to vendor ServiceId, but I dont + * have that yet, so just dump it as data. + */ + + /* fetch all octets in this sequence */ + + get_CDR_octet_seq(tvb, &context_data, offset, seqlen_cd); + + /* Make a printable string */ + + p_context_data = make_printable_string( context_data, seqlen_cd ); + + if(tree) { + proto_tree_add_text (tree, tvb, *offset - seqlen_cd , seqlen_cd, + "context_data: %s", p_context_data); + } + + g_free(context_data); + g_free(p_context_data); + + } /* seqlen */ + + + return; /* for now, fix later */ + + +} + +/* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15. + */ + +static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, + guint32 boundary) { + + guint32 length; /* string length */ + guint32 minor_code_value; + guint32 completion_status; + + gchar *buf = NULL; /* pointer to string buffer */ + + length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary); + + if (tree) { + proto_tree_add_text(tree, tvb, *offset-4, 4, + "Exception length: %u", length); + if (length > 0) { + proto_tree_add_text(tree, tvb, *offset - length, length, + "Exception id: %s", buf ); + } + } + + minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary); + completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary); + + if (tree) { + proto_tree_add_text(tree, tvb, *offset-8, 4, + "Minor code value: %u", minor_code_value); + proto_tree_add_text(tree, tvb, *offset-4, 4, + "Completion Status: %u", completion_status); + } +} + + +/* + * Helper functions for dissecting TypeCodes + * + * These functions decode the complex parameter lists + * of TypeCodes as defined in the CORBA spec chapter 15. + */ + +static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + guint32 seqlen; /* sequence length */ + + /* get sequence length, new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get repository ID */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_repoid); + + /* get name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_name); + +} + + +static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header ) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + guint32 count; /* parameter count (of tuples) */ + guint32 seqlen; /* sequence length */ + int i; /* loop index */ + + /* get sequence lengt,h new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get repository ID */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_repoid); + + /* get name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_name); + + /* get count of tuples */ + count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_typecode_count,tvb, + *offset-sizeof(count),4,count); + } + + /* get all tuples */ + for (i=0; i< count; i++) { + /* get member name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_member_name); + + /* get member type */ + get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header); + } + +} + + +static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + guint32 TCKind; /* TypeCode */ + gint32 s_octet4; /* signed int32 */ + + guint32 count; /* parameter count (of tuples) */ + guint32 seqlen; /* sequence length */ + int i; /* loop index */ + + /* get sequence legnth, new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get repository ID */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_repoid); + + /* get name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_name); + + /* get discriminant type */ + TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header); + + /* get default used */ + s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary); + if (tree) { + proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb, + *offset-sizeof(s_octet4),4,s_octet4); + } + /* get count of tuples */ + count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_typecode_count,tvb, + *offset-sizeof(count),4,count); + } + + /* get all tuples */ + for (i=0; i< count; i++) { + /* get label value, based on TCKind above */ + dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind ); + + /* get member name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_member_name); + + /* get member type */ + get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header); + } + +} + + +static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + guint32 count; /* parameter count (of tuples) */ + guint32 seqlen; /* sequence length */ + int i; /* loop index */ + + /* get sequence length, new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get repository ID */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_repoid); + + /* get name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_name); + + /* get count of tuples */ + count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_typecode_count,tvb, + *offset-sizeof(count),4,count); + } + + /* get all tuples */ + for (i=0; i< count; i++) { + /* get member name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_member_name); + } + +} + + +static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + guint32 u_octet4; /* unsigned int32 */ + + guint32 seqlen; /* sequence length */ + + /* get sequence length, new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get element type */ + get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header); + + /* get max length */ + u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb, + *offset-sizeof(u_octet4),4,u_octet4); + } +} + + +static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + guint32 u_octet4; /* unsigned int32 */ + + guint32 seqlen; /* sequence length */ + + /* get sequence length, new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get element type */ + get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header); + + /* get length */ + u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_typecode_length,tvb, + *offset-sizeof(u_octet4),4,u_octet4); + } +} + + +static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + guint32 seqlen; /* sequence length */ + + /* get sequence legnth, new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get repository ID */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_repoid); + + /* get name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_name); + + /* get ??? (noname) TypeCode */ + get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header); + +} + + +static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + guint32 count; /* parameter count (of tuples) */ + guint32 seqlen; /* sequence length */ + int i; /* loop index */ + + /* get sequence length, new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get repository ID */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_repoid); + + /* get name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_name); + + /* get count of tuples */ + count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_typecode_count,tvb, + *offset-sizeof(count),4,count); + } + + /* get all tuples */ + for (i=0; i< count; i++) { + /* get member name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_member_name); + + /* get member type */ + get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header); + } + +} + + +static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + gint16 s_octet2; /* signed int16 */ + + guint32 count; /* parameter count (of tuples) */ + guint32 seqlen; /* sequence length */ + int i; /* loop index */ + + /* get sequence length, new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get repository ID */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_repoid); + + /* get name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_name); + + /* get ValueModifier */ + s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb, + *offset-sizeof(s_octet2),2,s_octet2); + } + + /* get conrete base */ + get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header); + + /* get count of tuples */ + count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_typecode_count,tvb, + *offset-sizeof(count),4,count); + } + + /* get all tuples */ + for (i=0; i< count; i++) { + /* get member name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_member_name); + + /* get member type */ + get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header); + + /* get Visibility */ + s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb, + *offset-sizeof(s_octet2),2,s_octet2); + } + } + +} + + +static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + guint32 seqlen; /* sequence length */ + + /* get sequence length, new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get repository ID */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_repoid); + + /* get name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_name); + + /* get ??? (noname) TypeCode */ + get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header); +} + + +static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + guint32 seqlen; /* sequence length */ + + /* get sequence length, new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get repository ID */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_repoid); + + /* get name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_name); + +} + + +static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header) { + + guint32 new_boundary; /* new boundary for encapsulation */ + gboolean new_stream_is_big_endian; /* new endianness for encapsulation */ + + guint32 seqlen; /* sequence length */ + + /* get sequence length, new endianness and boundary for encapsulation */ + seqlen = get_CDR_encap_info(tvb, tree, offset, + stream_is_big_endian, boundary, + &new_stream_is_big_endian, &new_boundary); + + /* get repository ID */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_repoid); + + /* get name */ + dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary, + hf_giop_typecode_name); + +} + +/* Typecode parameter lists are encoded as encapsulations and + * this function gets the encapsulation information; see + * CORBA spec chapter 15 + * + * + * Renamed to get_CDR_encap_info() for any encapsulation + * we come across, useful helper function + * + * Also, should return immediately if seqlen == 0. + * ie: Forget about trying to grab endianess for + * zero length sequence. + * + * Caller must always check seqlen == 0, and not assume its value + * + * + * Note: there seemed to be considerable confusion in corba + * circles as to the correct interpretation of encapsulations, + * and zero length sequences etc, but this is our best bet at the + * moment. + * + * -- FS + * + */ + +guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean old_stream_is_big_endian, guint32 old_boundary, + gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) { + + guint32 seqlen; /* sequence length */ + guint8 giop_endianess; + + /* Get sequence length of parameter list */ + seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_sequence_length,tvb, + *offset-sizeof(seqlen),4,seqlen); + } + + + + /* + * seqlen == 0, implies no endianess and no data + * so just return. Populate new_boundary_ptr and + * new_stream_is_big_endian_ptr with current (old) + * values, just to keep everyone happy. -- FS + * + */ + + if (seqlen == 0) { + + *new_boundary_ptr = old_boundary; + *new_stream_is_big_endian_ptr = old_stream_is_big_endian; + + return seqlen; + + } + + /* Start of encapsulation of parameter list */ + *new_boundary_ptr = *offset; /* remember */ + giop_endianess = get_CDR_octet(tvb,offset); + + *new_stream_is_big_endian_ptr = ! giop_endianess; + + /* + * Glib: typedef gint gboolean; + * ie: It is not a guint8, so cannot use sizeof to correctly + * highlight octet. + */ + + + if (tree) { + proto_tree_add_uint(tree,hf_giop_endianess,tvb, + *offset-1,1,giop_endianess); + } + + + return seqlen; + + +} + +/* + * gets a TypeCode complex string parameter and + * displays it in the relevant tree. + */ + +static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) { + + guint32 u_octet4; /* unsigned int32 */ + gchar *buf = NULL; /* ptr to string buffer */ + + /* get string */ + u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary); + + if (tree) { + proto_tree_add_uint(tree,hf_giop_string_length,tvb, + *offset-u_octet4-sizeof(u_octet4),4,u_octet4); + if (u_octet4 > 0) { + proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf); + } + } + + g_free(buf); /* dont forget */ + +} + +/* + * For a given data type, given by a TypeCode gets the associated data + * and displays it in the relevant tree. + */ + +static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean stream_is_big_endian, guint32 boundary, + MessageHeader * header, guint32 data_type ) { + + gboolean my_boolean; /* boolean */ + + gint8 s_octet1; /* signed int8 */ + guint8 u_octet1; /* unsigned int8 */ + + gint16 s_octet2; /* signed int16 */ + guint16 u_octet2; /* unsigned int16 */ + + gint32 s_octet4; /* signed int32 */ + guint32 u_octet4; /* unsigned int32 */ + + gdouble my_double; /* double */ + gfloat my_float; /* float */ + + gchar *buf = NULL; /* ptr to string buffer */ + + /* Grab the data according to data type */ + + switch (data_type) { + case tk_null: + /* nothing to decode */ + break; + case tk_void: + /* nothing to decode */ + break; + case tk_short: + s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_int(tree,hf_giop_type_short,tvb, + *offset-sizeof(s_octet2),2,s_octet2); + } + break; + case tk_long: + s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_int(tree,hf_giop_type_long,tvb, + *offset-sizeof(s_octet4),4,s_octet4); + } + break; + case tk_ushort: + u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_type_ushort,tvb, + *offset-sizeof(u_octet2),2,u_octet2); + } + break; + case tk_ulong: + u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_type_ulong,tvb, + *offset-sizeof(u_octet4),4,u_octet4); + } + break; + case tk_float: + my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_double(tree,hf_giop_type_float,tvb, + *offset-sizeof(my_float),4,my_float); + } + break; + case tk_double: + my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_double(tree,hf_giop_type_double,tvb, + *offset-sizeof(my_double),8,my_double); + } + break; + case tk_boolean: + my_boolean = get_CDR_boolean(tvb,offset); + if (tree) { + proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb, + *offset-1,1,my_boolean); + } + break; + case tk_char: + u_octet1 = get_CDR_char(tvb,offset); + if (tree) { + proto_tree_add_uint(tree,hf_giop_type_char,tvb, + *offset-sizeof(u_octet1),1,u_octet1); + } + break; + case tk_octet: + u_octet1 = get_CDR_octet(tvb,offset); + if (tree) { + proto_tree_add_uint(tree,hf_giop_type_octet,tvb, + *offset-sizeof(u_octet1),1,u_octet1); + } + break; + case tk_any: + get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header); + break; + case tk_TypeCode: + get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header); + break; + case tk_Principal: + break; + case tk_objref: + break; + case tk_struct: + break; + case tk_union: + break; + case tk_enum: + u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_type_enum,tvb, + *offset-sizeof(u_octet4),4,u_octet4); + } + break; + case tk_string: + u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary); + if (tree) { + proto_tree_add_uint(tree,hf_giop_string_length,tvb, + *offset-u_octet4-sizeof(u_octet4),4,u_octet4); + if (u_octet4 > 0) { + proto_tree_add_string(tree,hf_giop_type_string,tvb, + *offset-u_octet4,u_octet4,buf); + } + } + + g_free(buf); /* dont forget */ + break; + case tk_sequence: + break; + case tk_array: + break; + case tk_alias: + break; + case tk_except: + break; + case tk_longlong: + break; + case tk_ulonglong: + break; + case tk_longdouble: + break; + case tk_wchar: + s_octet1 = get_CDR_wchar(tvb,&buf,offset,header); + if (tree) { + if (s_octet1 < 0) { /* no size to add to tree */ + proto_tree_add_string(tree,hf_giop_type_string,tvb, + *offset+s_octet1,(-s_octet1),buf); + } else { + proto_tree_add_uint(tree,hf_giop_string_length,tvb, + *offset-s_octet1-sizeof(s_octet1),1,s_octet1); + proto_tree_add_string(tree,hf_giop_type_string,tvb, + *offset-s_octet1,s_octet1,buf); + } + } + + g_free(buf); /* dont forget */ + break; + case tk_wstring: + u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header); + if (tree) { + proto_tree_add_uint(tree,hf_giop_string_length,tvb, + *offset-u_octet4-sizeof(u_octet4),4,u_octet4); + proto_tree_add_string(tree,hf_giop_type_string,tvb, + *offset-u_octet4,u_octet4,buf); + } + + g_free(buf); /* dont forget */ + break; + case tk_fixed: + break; + case tk_value: + break; + case tk_value_box: + break; + case tk_native: + break; + case tk_abstract_interface: + break; + default: + g_warning("giop: Unknown typecode data type %u \n", data_type); + break; + } /* data_type */ + } diff --git a/packet-giop.h b/packet-giop.h new file mode 100644 index 0000000000..2326d3a803 --- /dev/null +++ b/packet-giop.h @@ -0,0 +1,572 @@ +/* packet-giop.h + * Declarations of outines for GIOP (CDR) dissection + * Copyright 2000, Frank Singleton <frank.singleton@ericsson.com> + * + * Based on CORBAv2.4.2 Chapter 15 GIOP Description. + * + * $Id: packet-giop.h,v 1.3 2001/06/18 05:27:16 guy Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * 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. + */ + +#ifndef PACKET_GIOP_H +#define PACKET_GIOP_H + +/* + * Useful visible data/structs + */ + +#define GIOP_HEADER_SIZE 12 + +typedef struct Version { + guint8 major; + guint8 minor; +} Version; + + +/* + * Useful data collected from message header. Note, this + * struct encapsulates useful data from GIOP header, as well + * as request_id and reply_status for use by sub dissectors. + */ + +typedef struct MessageHeader { + + /* Common Data */ + + guint8 magic[4]; + Version GIOP_version; + guint8 flags; /* byte_order in 1.0 */ + guint8 message_type; + guint32 message_size; + guint32 req_id; /* request id in MSG */ + + /* MSG dependant data */ + + guint32 rep_status; /* reply status in MSG if available */ + gchar *exception_id; /* exception string if a USER EXCEPTION occurs */ + +} MessageHeader; + +typedef enum MsgType { + Request = 0, + Reply, + CancelRequest, + LocateRequest, + LocateReply, + CloseConnection, + MessageError, + Fragment /* GIOP 1.1 only */ + +} MsgType; + + + +/* + * Reply Status + * + */ + +typedef enum ReplyStatusType { + NO_EXCEPTION = 0, + USER_EXCEPTION, + SYSTEM_EXCEPTION, + LOCATION_FORWARD, + LOCATION_FORWARD_PERM, /* new for GIOP 1.2 */ + NEEDS_ADDRESSING_MODE /* new for GIOP 1.2 */ +} ReplyStatusType; + +/* + * Prototype for sub dissector function calls. + */ + +typedef gboolean (giop_sub_dissector_t)(tvbuff_t *, packet_info *, proto_tree *, int *, + MessageHeader *, gchar * , gchar *); + +/* + * Generic Subdissector handle, wraps user info. + */ + +typedef struct giop_sub_handle { + giop_sub_dissector_t *sub_fn; /* ptr to sub dissector function */ + gchar *sub_name; /* subdissector string name */ + +} giop_sub_handle_t; + +/* Main GIOP entry point */ + +gboolean dissect_giop(tvbuff_t *, packet_info *, proto_tree *); /* new interface */ + +/* + * GIOP Users register interest via this function. + * This is for heuristic dissection + */ + +void register_giop_user(giop_sub_dissector_t *sub, gchar *name); + +/* + * GIOP Users remove interest via this function. + * This is for heuristic dissection + */ + +void delete_giop_user(giop_sub_dissector_t *sub, gchar *name); + + +/* + * GIOP Users register their module and interface names via this function. + * This is for explicit dissection. + */ + +void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module); + +/* + * GIOP Users remove their module and interface names via this function. + * This is for explicit dissection. + */ + +void delete_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module); + + +/* + * General CDR accessors start here. They are listed in alphabetical + * order. They may however, belong to 1 of 3 distinct CDR data types. + * + * - Primitive + * - OMG IDL Constructed Types + * - Pseudo Object Types + * + * + * Altough some of these look redundant, I have separated them + * out for all CDR types, to assist in auto generation of + * IDL dissectors later, see idl2eth -- FS + * + */ + + +/* + * Gets data of type any. This is encoded as a TypeCode + * followed by the encoded value. + * + * Data is added to tree directly if present. + */ + +void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset, gboolean stream_is_big_endian, + int boundary, MessageHeader * header ); + + +/* Copy a 1 octet sequence from the tvbuff + * which represents a boolean value, and convert + * it to a boolean value. + * Offset is then incremented by 1, to indicate the 1 octet which + * has been processed. + */ + +gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset); + + +/* Copy a 1 octet sequence from the tvbuff + * which represents a char, and convert + * it to an char value. + * offset is then incremented by 1, to indicate the 1 octet which + * has been processed. + */ + +guint8 get_CDR_char(tvbuff_t *tvb, int *offset); + + + +/* + * Floating Point Data Type double IEEE 754-1985 + * + * Copy an 8 octet sequence from the tvbuff + * which represents a double value, and convert + * it to a double value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for double values. + * offset is then incremented by 8, to indicate the 8 octets which + * have been processed. + */ + +gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary); + + +/* Copy a 4 octet sequence from the tvbuff + * which represents an enum value, and convert + * it to an enum value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for an enum (4) + * offset is then incremented by 4, to indicate the 4 octets which + * have been processed. + * + * Enum values are encoded as unsigned long. + */ + +guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary); + + +/* + * Copy an "n" octet sequence from the tvbuff + * which represents a Fixed point decimal type, and convert + * it to a Fixed point decimal type. There are no alignment restrictions. + * Size of fixed decimal type is determined by IDL, but this routine + * will just process octets until it hits the "sign configuration" as + * the last octet. + * + * This value is either + * 0xd - positive value + * 0xc - negative value + * + * offset is then incremented past the sign octet. + * + */ + +void get_CDR_fixed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset, guint32 n); + + + +/* + * Floating Point Data Type float IEEE 754-1985 + * + * Copy a 4 octet sequence from the tvbuff + * which represents a float value, and convert + * it to a float value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for float values. + * offset is then incremented by 4, to indicate the 4 octets which + * have been processed. + */ + +gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary); + + +/* + * Decode an Interface type, and display it on the tree. + */ + +void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + gboolean stream_is_big_endian, int boundary); + + +/* Copy a 4 octet sequence from the tvbuff + * which represents a signed long value, and convert + * it to an signed long vaule, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for long values. + * offset is then incremented by 4, to indicate the 4 octets which + * have been processed. + */ + +gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary); + + + +/* Copy a 16 octet sequence from the tvbuff + * which represents a long double value, and convert + * it to a long double value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for long double values. + * offset is then incremented by 16, to indicate the 16 octets which + * have been processed. + */ + +#ifdef G_HAVE_GLONG_DOUBLE + +glong_double get_CDR_long_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, + int boundary); +#else + +/* FIX -- Cast long double to gdouble until I figure this out -- FS*/ + +gdouble get_CDR_long_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, + int boundary); + +#endif + + +/* Copy an 8 octet sequence from the tvbuff + * which represents a signed long long value, and convert + * it to a signed long long value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for long long values. + * offset is then incremented by 8, to indicate the 8 octets which + * have been processed. + */ + +#ifdef G_HAVE_GINT64 +gint64 get_CDR_long_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary); +#endif + +/* + * Decode an Object type, and display it on the tree. + */ + +void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, + gboolean stream_is_big_endian, int boundary); + + +/* Copy a 1 octet sequence from the tvbuff + * which represents a octet, and convert + * it to an octet value. + * offset is then incremented by 1, to indicate the 1 octet which + * has been processed. + */ + +guint8 get_CDR_octet(tvbuff_t *tvb, int *offset); + + +/* Copy a sequence of octets from the tvbuff. + * Caller of this function must remember to free the + * array pointed to by seq. + * This function also increments offset by len. + */ + +void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, int len); + +/* Copy a 2 octet sequence from the tvbuff + * which represents a signed short value, and convert + * it to a signed short value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for short values. + * offset is then incremented by 2, to indicate the 2 octets which + * have been processed. + */ + +gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary); + + +/* Copy an octet sequence from the tvbuff + * which represents a string, and convert + * it to an string value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for string values. (begins with an unsigned long LI) + * + * String sequence is copied to a buffer "seq". This must + * be freed by the calling program. + * offset is then incremented , to indicate the octets which + * have been processed. + * + * returns number of octets in the sequence + * + * Note: This function only supports single byte encoding at the + * moment until I get a handle on multibyte encoding etc. + * + */ + +guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian, + int boundary); + + +/* Process a sequence of octets that represent the + * Pseudo Object Type "TypeCode". Typecodes are used for example, + * by "Any values". + * This function also increments offset to the correct position. + * + * It will parse the TypeCode and output data to the "tree" provided + * by the user + * + * It returns a guint32 representing a TCKind value. + */ + +guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset, gboolean stream_is_big_endian, + int boundary, MessageHeader * header ); + +/* Copy a 4 octet sequence from the tvbuff + * which represents an unsigned long value, and convert + * it to an unsigned long value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for unsigned long values. + * offset is then incremented by 4, to indicate the 4 octets which + * have been processed. + */ + +guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary); + + +/* Copy an 8 octet sequence from the tvbuff + * which represents an unsigned long long value, and convert + * it to an unsigned long long value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for unsigned long long values. + * offset is then incremented by 8, to indicate the 8 octets which + * have been processed. + */ + +#ifdef G_HAVE_GINT64 +guint64 get_CDR_ulong_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary); +#endif + + +/* Copy a 2 octet sequence from the tvbuff + * which represents an unsigned short value, and convert + * it to an unsigned short value, taking into account byte order. + * offset is first incremented so that it falls on a proper alignment + * boundary for unsigned short values. + * offset is then incremented by 2, to indicate the 2 octets which + * have been processed. + */ + +guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary); + + +/* Copy a wchar from the tvbuff. + * Caller of this function must remember to free the + * array pointed to by seq. + * This function also increments offset according to + * the wchar size. + * + * For GIOP 1.1 read 2 octets and return size -2. The + * negation means there is no size element in the packet + * and therefore no size to add to the tree. + * + * For GIOP 1.2 read size of wchar and the size + * octets. size is returned as a gint8. + * + * For both GIOP versions the wchar is returned + * as a printable string. + * + */ + +/* NOTE: This is very primitive in that it just reads + * the wchar as a series of octets and returns them + * to the user. No translation is attempted based on + * byte orientation, nor on code set. I.e it only + * really reads past the wchar and increments the offset + * by the length of the octet sequence. + */ + +/* The "decoding" is done according to CORBA chapter 15. + * Wchar is not supported for GIOP 1.0. + */ + +gint8 get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header); + + +/* Copy a wstring from the tvbuff. + * Caller of this function must remember to free the + * array pointed to by seq. + * This function also increments offset, according to + * wstring length. length is returned as guint32 + */ + +/* NOTE: This is very primitive in that it just reads + * the wstring as a series of octets and returns them + * to the user. No translation is attempted based on + * byte orientation, nor on code set. I.e it only + * really reads past the wstring and increments the offset + * by the length of the octet sequence. + */ + +/* The "decoding" is done according to CORBA chapter 15. + * Wstring is not supported for GIOP 1.0. + */ + +guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian, + int boundary, MessageHeader * header); + + + +/* + * + * End of get_CDR_xxx accessors. + * + */ + + + +/* Determine the byte order from the GIOP MessageHeader */ + +gboolean is_big_endian (MessageHeader * header); + +/* + * get_encap_info() for any encapsulation (eg:sequences) + * we come across. updates the new boundary and endianess + * and *offset, and returns the sequence length. + */ + +guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset, + gboolean old_stream_is_big_endian, guint32 old_boundary, + gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ); + + + +/* + * Enums for TCkind + */ + +enum TCKind { + tk_null = 0, + tk_void, + tk_short, + tk_long, + tk_ushort, + tk_ulong, + tk_float, + tk_double, + tk_boolean, + tk_char, + tk_octet, + tk_any, + tk_TypeCode, + tk_Principal, + tk_objref, + tk_struct, + tk_union, + tk_enum, + tk_string, + tk_sequence, + tk_array, + tk_alias, + tk_except, + tk_longlong, + tk_ulonglong, + tk_longdouble, + tk_wchar, + tk_wstring, + tk_fixed, + tk_value, + tk_value_box, + tk_native, + tk_abstract_interface, + + /* - none - 0xffffffff TODO */ +}; + +#define tk_none 0xffffffff + +typedef enum TCKind TCKind_t; + + +/* + * ServiceId's for ServiceContextList + * + * Chapter 13 Corba 2.4.2 + */ + +#define IOP_ServiceId_TransactionService 0 +#define IOP_ServiceId_CodeSets 1 +#define IOP_ServiceId_ChainBypassCheck 2 +#define IOP_ServiceId_ChainBypassInfo 3 +#define IOP_ServiceId_LogicalThreadId 4 +#define IOP_ServiceId_BI_DIR_IIOP 5 +#define IOP_ServiceId_SendingContextRunTime 6 +#define IOP_ServiceId_INVOCATION_POLICIES 7 +#define IOP_ServiceId_FORWARD_IDENTITY 8 +#define IOP_ServiceId_UnknownExceptionInfo 9 + +#endif /* PACKET_GIOP_H */ |