aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--Makefile.am11
-rw-r--r--doc/README.idl2eth103
-rw-r--r--ethereal_be.py134
-rw-r--r--ethereal_gen.py1521
-rwxr-xr-xidl2eth56
-rw-r--r--packet-giop.c4972
-rw-r--r--packet-giop.h572
8 files changed, 6814 insertions, 556 deletions
diff --git a/AUTHORS b/AUTHORS
index f789fdd147..fe436156cd 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -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 */