2 * Routines for CORBA GIOP/IIOP packet disassembly
5 * Laurent Deniel <deniel@worldnet.fr>
6 * Craig Rodrigues <rodrigc@mediaone.net>
8 * GIOP API extensions by,
9 * Frank Singleton <frank.singleton@ericsson.com>
10 * Trevor Shepherd <eustrsd@am1.ericsson.se>
12 * $Id: packet-giop.c,v 1.51 2001/12/15 20:40:18 guy Exp $
14 * Ethereal - Network traffic analyzer
15 * By Gerald Combs <gerald@ethereal.com>
16 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 * 1. heuristic giop dissector table [started]
37 * 2. GUI options, see 20
38 * 3. Remove unneccessary reply_status in heuristic dissector calls (now
39 * part of MessageHeader) [done]
40 * 4. get_CDR_xxx should be passed an alignment offset value
41 * rather than GIOP_HEADER_SIZE, as alignment can also change in a
42 * octet stream when eg: encapsulation is used [done]
43 * 5. GIOP users should eventually get there own tvbuff, and
44 * not rely on the GIOP tvbuff, more robust
45 * 6. get_CDR_string,wchar,wstring etc should handle different
46 * GIOP versions [started]
47 * 7. Fix situation where req_id is not unique in a logfile [done, use FN/MFN, needs improving.]
49 * 8. Keep request_1_2 in step with request_1_1 [started]
50 * 9. Explicit module name dissection [done]
51 * 10. Decode IOR and put in a useful struct [IOR decode started]
52 * 11. Fix encapsulation of IOR etc and boundary [done]
53 * 12. handle get_CDR_typeCode() [started]
54 * 13. Handle different IOR profiles
55 * 14. Change printable_string to RETURN a new string, not to modify the old.
56 * or, new function, make_printable_string [done, make_printable_string]
58 * 15. Handle "TCKind", and forget about eg: enum translation to symbolic values
59 * otherwise need knowledge of sub dissectors data - YUK [done]
60 * 16. Handle multiple RepoId representations, besides IDL:Echo:1.0 (see 13.)
61 * 17. Pass subset of RepoID to explicit dissector.
62 * eg : If IDL:Mod1/Mod2/Int3:1.0 then pass "Mod1/Mode2/Int3" to sub dissector[done]
63 * 18. Better hashing algorithms
64 * 19. Handle hash collision properly .
65 * 20. Allow users to paste a stringified IOR into the GUI, and tie it
67 * 21. Add complete_request_packet_list and complete_reply_packet_hash.[done]
68 * 22. Handle case where users click in any order, AND try and match
69 * REPLY msg to the correct REQUEST msg when we have a request_id collision.[done]
70 * 23. Clean up memory management for all those g_malloc's etc
71 * 24. register_giop_user_module could return a key for every distinct Module/Interface
72 * the sub_dissector uses. So, instead of strcmp()'s when handling the
73 * namespace of an operation, we could have a lookup table instead.
74 * 25. A few typedefs in the right place.
75 * 26 Improve handling of gchar * and use const gchar * where possible.
76 * 27. Read/write IOR etc to/from file, allows objkey hash to be built from
77 * external data [read done, write incomplete]
78 * 28. Call sub dissector only if tvb_offset_exists(). [Done, this is checked
79 * inside try_explicit_giop_dissector() ]
81 * 29. Make add/delete routine for objkey hash as it may be useful when say reading
82 * stringified IOR's from a file to add them to our hash. ie: There are other ways
83 * to populate our object key hash besides REPLY's to RESOLVE(request) [done]
85 * 30. Add routine to encode/decode stringified IOR's [decode done]
86 * 31. Add routine to read IOR's from file [done]
87 * 32. TypeCode -none-, needs decoding.
88 * 33. Complete dissect_data_for_typecode.
89 * 34. For complex TypeCodes need to check final offset against original offset + sequence length.
90 * 35. Update REQUEST/REPLY 1_2 according to IDL (eg; ServiceContextList etc).
91 * 36. Adding decode_ServiceContextList, incomplete.
92 * 37. Helper functions should not ALWAYS rely on header to find current endianess. It should
93 * be passed from user, eg Use stream_is_big_endian. [started]
94 * 38. Remove unwanted/unused function parameters, see decode_IOR [started]
95 * 40. Add sequence <IOP::TaggedComponent> components to IIOP IOR profile. Perhaps
96 * decode_IOP_TaggedComponents as a helper function. [done - NOT helper]
98 * 41. Make important field searchable from Message header. ie: Remove add_text_
99 * 42. Use sub-tree for decode_ServiceContextList, looks better.
100 * 43. dissect_reply_body, no exception dissector calls
101 * - call subdiss directly, as we already have handle.
102 * - add repoid to heuristic call also.
104 * 44. typedef using xxx_t in .h file.
105 * 45. Subdissectors should not be passed MessageHeader to find endianness and
106 * version, they should be passed directly ?
107 * 46. get_CDR_wchar and wstring need wide chars decoded (just dumped in
108 * any readable form at present, not handled well at all, suggestions welcome -- FS
109 * 47. Change ...add_text to ...add_xxx (ie use hf fields).
111 * 48. BUG - file load with a GIOP filter set, causes the FN/MFN data struct to be
112 * not initiated properly. Hit "Reload" as a workaround, til I fix this -- FS
119 * Intended Decode strategy:
120 * =========================
124 * REQUEST: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
125 * and populate complete_request_packet_hash
127 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
132 * REQUEST: FN -> giop_sub_handle_t directly (via complete_request_packet_hash)
134 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
135 * (via complete_request_packet_hash
141 * 1. Request_ID's are unique only per connection.
143 * 2. You must be monitoring the network when the client does
144 * a REQUEST(resolve), otherwise I have no knowledge of the
145 * association between object_key and REPOID. I could talk to
146 * a Nameserver, but then I would start "generating" packets.
147 * This is probably not a good thing for a protocol analyser.
148 * Also, how could I decode logfiles offline.
150 * TODO -- Read stringified IORs from an input file.[done]
152 * 3. User clicks (REQUEST) is currently handle the same as
153 * the initial pass handling.
155 * ie: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
160 * Important Data Structures:
165 * This is a hash table that maps IDL Module/Interface Names (Key)
166 * to sub_dissector handles, giop_sub_handle_t. It is populated
167 * by subdissectors, via register_giop_user_module(). This
168 * table is used when we have a REPOID, and explicitly wish to
169 * call the subdissector that has registered responsibility for
170 * that IDL module/interface.
176 * This singly linked list is used to hold entries for
177 * heuristic based subdissectors. It is populated by sub_dissectors
178 * wishing to be called via heuristic mechanisms. They do this
179 * via the register_giop_user() function.
185 * This hash table maps object_key's (key) onto REPOID's (val).
186 * Once a client has REQUEST(resolve) an object , it knows about
187 * an object (interface) via its object_key (see IOR). So in order to follow
188 * packets that contain an object_key only, and to be able to forward it
189 * to the correct explicit subdissector, we need this table.
191 * So, I listen in on REQUEST(resolve) messages between client and
192 * Nameserver, and store the respones (REPLY/Objkey,Repo_ID) here.
194 * Also, stringified IOR's can be read from a file "IOR.txt" and used
195 * to populate this hash also.
198 * Other Data structures
199 * =======================
201 * These structures have been added to minimise the possibility
202 * of incorrectly interpreted packets when people click all
203 * over the place, in no particular order, when the request_id's are
204 * not unique as captured. If all request_is'd are unique, as captured, then
205 * we would not have to deal with this problem.
208 * When the logfile or packets are initially being processed, I will
209 * build 2 structures. The intent is to be able to map a REPLY message
210 * back to the most recent REQUEST message with the same Request_ID
211 * (TODO and matching port and IP address ??)
217 * MFN - Matching Frame Number
220 * complete_request_packet_list
221 * ----------------------------
223 * This is a list that contains ALL the FN's that are REQUEST's, along with
224 * operation,request_id and giop_sub_handle_t
226 * complete_reply_packet_hash
227 * --------------------------
229 * This is a hash table. It is populated with FN (key) and MFN (val).
230 * This allows me to handle the case, where if you click on any REPLY
231 * message, I can lookup the matching request. This can improve
232 * the match rate between REQUEST and REPLY when people click in
233 * any old fashion, but is NOT foolproof.
235 * The algorithm I use to populate this hash during initial pass,
238 * If packet is a REPLY, note the reqid, and then traverse backwards
239 * through the complete_request_packet_list from its tail, looking
240 * for a FN that has the same Request_id. Once found, take the found FN
241 * from complete_reply_packet_hash, and insert it into the MFN field
242 * of the complete_reply_packet_hash.
245 * See TODO for improvements to above algorithm.
247 * So now when people click on a REQUEST packet, I can call lookup the
248 * giop_sub_handle_t directly from complete_request_packet_list.
250 * And, when they click on a REPLY, I grab the MFN of this FN from
251 * complete_reply_packet_hash, then look that up in the complete_request_packet_list
252 * and call the sub_dissector directly.
254 * So, how do I differentiate between the initial processing of incoming
255 * packets, and a user clickin on one ? Good question.
257 * I leverage the pinfo_fd->flags.visited on a per frame
260 * To quote from the ever helpful development list
262 * " When a capture file is initially loaded, all "visited" flags
263 * are 0. Ethereal then makes the first pass through file,
264 * sequentially dissecting each packet. After the packet is
265 * dissected the first time, "visited" is 1. (See the end of
266 * dissect_packet() in epan/packet.c; that's the code that
267 * sets "visited" to 1).
269 * By the time a user clicks on a packet, "visited" will already
270 * be 1 because Ethereal will have already done its first pass
271 * through the packets.
273 * Reload acts just like a normal Close/Open, except that it
274 * doesn't need to ask for a filename. So yes, the reload button
275 * clears the flags and re-dissects the file, just as if the file
276 * had been "opened". "
285 #ifdef HAVE_SYS_TYPES_H
286 # include <sys/types.h>
295 #ifdef NEED_STRERROR_H
296 #include "strerror.h"
300 #include "packet-giop.h"
303 * This affects how we handle context_data inside ServiceContext structs.
304 * According to CORBA 2.4.2, Context data is encapsulated in octet sequences,
305 * but so far I haven't seen the that on the wire. But, maybe its me -- FS
309 #define CONTEXT_DATA_IS_ENCAPSULATED 0
313 * Set to 1 for DEBUG output - TODO make this a runtime option
321 * ------------------------------------------------------------------------------------------+
322 * Private Helper function Declarations
323 * ------------------------------------------------------------------------------------------+
327 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
328 guint32 boundary, gboolean new_endianess, gchar *repobuf,
329 gboolean store_flag);
331 static void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
332 gboolean stream_is_be, guint32 boundary);
334 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
335 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf);
337 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
338 guint32 boundary, gboolean stream_is_big_endian );
340 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
341 gboolean stream_is_big_endian,
344 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
345 gboolean stream_is_big_endian, guint32 boundary,
346 MessageHeader * header);
348 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
349 gboolean stream_is_big_endian, guint32 boundary,
350 MessageHeader * header);
352 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
353 gboolean stream_is_big_endian, guint32 boundary,
354 MessageHeader * header );
356 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
357 gboolean stream_is_big_endian, guint32 boundary,
358 MessageHeader * header);
360 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
361 gboolean stream_is_big_endian, guint32 boundary,
362 MessageHeader * header);
364 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
365 gboolean stream_is_big_endian, guint32 boundary,
366 MessageHeader * header);
368 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
369 gboolean stream_is_big_endian, guint32 boundary,
370 MessageHeader * header);
372 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
373 gboolean stream_is_big_endian, guint32 boundary,
374 MessageHeader * header);
376 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
377 gboolean stream_is_big_endian, guint32 boundary,
378 MessageHeader * header);
380 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
381 gboolean stream_is_big_endian, guint32 boundary,
382 MessageHeader * header);
384 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
385 gboolean stream_is_big_endian, guint32 boundary,
386 MessageHeader * header);
388 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
389 gboolean stream_is_big_endian, guint32 boundary,
390 MessageHeader * header);
393 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
394 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
396 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
397 gboolean stream_is_big_endian, guint32 boundary,
398 MessageHeader * header, guint32 data_type );
404 * ------------------------------------------------------------------------------------------+
405 * Data/Variables/Structs
406 * ------------------------------------------------------------------------------------------+
410 static int proto_giop = -1;
411 static int hf_giop_message_type = -1;
412 static int hf_giop_message_size = -1;
413 static int hf_giop_repoid = -1;
414 static int hf_giop_string_length = -1;
415 static int hf_giop_sequence_length = -1;
416 static int hf_giop_profile_id = -1;
417 static int hf_giop_type_id = -1;
418 static int hf_giop_iiop_v_maj = -1;
419 static int hf_giop_iiop_v_min = -1;
420 static int hf_giop_endianess = -1; /* esp encapsulations */
421 static int hf_giop_IOR_tag = -1;
422 static int hf_giop_IIOP_tag = -1;
424 static int hf_giop_TCKind = -1;
425 static int hf_giop_typecode_count = -1;
426 static int hf_giop_typecode_default_used = -1;
427 static int hf_giop_typecode_digits = -1;
428 static int hf_giop_typecode_length = -1;
429 static int hf_giop_typecode_max_length = -1;
430 static int hf_giop_typecode_member_name = -1;
431 static int hf_giop_typecode_name = -1;
432 static int hf_giop_typecode_scale = -1;
433 static int hf_giop_typecode_ValueModifier = -1;
434 static int hf_giop_typecode_Visibility = -1;
436 static int hf_giop_type_boolean = -1;
437 static int hf_giop_type_char = -1;
438 static int hf_giop_type_double = -1;
439 static int hf_giop_type_enum = -1;
440 static int hf_giop_type_float = -1;
441 static int hf_giop_type_long = -1;
442 static int hf_giop_type_octet = -1;
443 static int hf_giop_type_short = -1;
444 static int hf_giop_type_string = -1;
445 static int hf_giop_type_ulong = -1;
446 static int hf_giop_type_ushort = -1;
448 static int hf_giop_iiop_host = -1;
449 static int hf_giop_iiop_port = -1;
450 static int hf_giop_iop_vscid = -1;
451 static int hf_giop_iop_scid = -1;
457 static gint ett_giop = -1;
458 static gint ett_giop_reply = -1;
459 static gint ett_giop_request = -1;
460 static gint ett_giop_cancel_request = -1;
461 static gint ett_giop_locate_request = -1;
462 static gint ett_giop_locate_reply = -1;
463 static gint ett_giop_fragment = -1;
465 static gint ett_giop_scl = -1; /* ServiceContextList */
466 static gint ett_giop_ior = -1; /* IOR */
468 static dissector_handle_t data_handle;
471 static const value_string giop_endianess_vals[] = {
472 { 0x0, "Big Endian" },
473 { 0x1, "Little Endian" },
477 static const value_string sync_scope[] = {
478 { 0x0, "SYNC_NONE" },
479 { 0x1, "SYNC_WITH_TRANSPORT"},
480 { 0x2, "SYNC_WITH_SERVER"},
481 { 0x3, "SYNC_WITH_TARGET"},
487 static const value_string profile_id_vals[] = {
488 { 0x0, "TAG_INTERNET_IOP" },
489 { 0x1, "TAG_MULTIPLE_COMPONENTS"},
490 { 0x2, "TAG_SCCP_IOP"},
494 static const value_string giop_message_types[] = {
497 { 0x2, "CancelRequest"},
498 { 0x3, "LocateRequest"},
499 { 0x4, "LocateReply"},
500 { 0x5, "CloseConnection"},
501 { 0x6, "MessageError"},
506 static const value_string giop_locate_status_types[] = {
507 { 0x0, "Unknown Object" },
508 { 0x1, "Object Here"},
509 { 0x2, "Object Forward"},
510 { 0x3, "Object Forward Perm"},
511 { 0x4, "Loc System Exception"},
512 { 0x5, "Loc Needs Addressing Mode"},
516 static const value_string tckind_vals[] = {
529 { 12, "tk_TypeCode"},
530 { 13, "tk_Principal"},
536 { 19, "tk_sequence"},
540 { 23, "tk_longlong"},
541 { 24, "tk_ulonglong"},
542 { 25, "tk_longdouble"},
547 { 30, "tk_value_box"},
549 { 32, "tk_abstract_interface"},
555 #define GIOP_MAGIC "GIOP"
558 * TAGS for IOR Profiles
560 * Chapter 13 Corba 2.4.2
564 #define IOP_TAG_INTERNET_IOP 0
565 #define IOP_TAG_MULTIPLE_COMPONENTS 1
568 /* Max Supported versions */
570 static const guint GIOP_MAJOR = 1;
571 static const guint GIOP_MINOR = 2;
574 static const int KeyAddr = 0;
575 static const int ProfileAddr = 1;
576 static const int ReferenceAddr = 2;
580 static const value_string reply_status_types[] = {
581 { NO_EXCEPTION, "No Exception" } ,
582 { USER_EXCEPTION, "User Exception" } ,
583 { SYSTEM_EXCEPTION, "System Exception" } ,
584 { LOCATION_FORWARD, "Location Forward" } ,
585 { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
586 { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
592 typedef enum LocateStatusType
597 OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
598 LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
599 LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
603 typedef struct LocateReplyHeader
606 guint32 locate_status;
612 * DATA - complete_request_list
615 static GList *giop_complete_request_list;
617 struct comp_req_list_entry {
618 guint32 fn; /* frame number */
619 gchar * operation; /* echo echoString */
620 giop_sub_handle_t *subh; /* handle to sub dissector */
621 guint32 reqid; /* request id */
622 gchar * repoid; /* repository ID */
625 typedef struct comp_req_list_entry comp_req_list_entry_t;
629 * DATA - complete_reply_hash
631 * Maps reply FN to request MFN
634 static int complete_reply_hash_count = 1000; /* storage size for our permanent data */
635 /* ie: 1000 entries -- needs tweaking -- FS */
637 struct complete_reply_hash_key {
638 guint32 fn; /* reply frame number */
641 struct complete_reply_hash_val {
642 guint32 mfn; /* matching frame number (request) */
645 GHashTable *giop_complete_reply_hash = NULL; /* hash */
646 GMemChunk *giop_complete_reply_keys = NULL; /* key storage */
647 GMemChunk *giop_complete_reply_vals = NULL; /* val storage */
651 * DATA - Module Hash stuff to store data from register_giop_user_module
653 * ie: module (or interface ?) name, and ptr to sub_dissector handle
655 * With this knowledge, we can call a sub dissector directly,
658 * objkey -> repoid -> sub_dissector via registered module/interface
663 static int giop_module_init_count = 100; /* storage size for our permanent data */
664 /* ie: 100 entries -- needs tweaking -- FS */
666 struct giop_module_key {
667 gchar *module; /* module (interface?) name */
670 struct giop_module_val {
671 giop_sub_handle_t *subh; /* handle to sub dissector */
674 GHashTable *giop_module_hash = NULL; /* hash */
675 GMemChunk *giop_module_keys = NULL; /* key storage */
676 GMemChunk *giop_module_vals = NULL; /* val storage */
680 * DATA - GSList to store list of function (dissector) pointers.
681 * for heuristic dissection.
685 static GSList *giop_sub_list = NULL;
688 * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
689 * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
691 * With this knowledge, we can call a sub dissector directly later
694 * objkey -> repoid -> sub_dissector via registered module/interface
696 * rather than heuristic calls that do not provide operation context.
697 * (unless we pass the RepoID for a given objkey -- hmmm)
702 * Interesting operation list, add more if you want to save
706 static const char giop_op_resolve[] = "resolve";
707 static const char giop_op_bind_new_context[] = "bind_new_context";
708 static const char giop_op_bind[] = "bind";
711 * Enums for interesting local operations, that we may need to monitor
712 * with their subsequent replies
717 request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
718 request_bind_new_context_op_val, /* bind_new_context */
719 request_bind_op_val, /* bind */
720 request_get_INIT_op_val, /* finding Nameserver */
726 * hash for mapping object keys onto object namespaces, so
727 * I can call the correct dissector.
733 * Where did I get the IOR from.
737 req_res = 0, /* REQUEST (resolve) */
738 file, /* stringified IOR' in a file */
742 typedef enum ior_src ior_src_t;
747 * Enums for my lists and hash's
750 enum collection_data {
751 cd_heuristic_users = 0,
754 cd_complete_request_list,
755 cd_complete_reply_hash
758 typedef enum collection_data collection_data_t;
762 static int giop_objkey_init_count = 100; /* storage size for our permanent data */
763 /* ie: 100 entries -- needs tweaking -- FS */
765 struct giop_object_key {
766 guint8 *objkey; /* ptr to object key */
767 guint32 objkey_len; /* length */
770 struct giop_object_val {
771 guint8 *repo_id; /* ptr to Repository ID string */
772 ior_src_t src; /* where did Iget this IOR from */
775 GHashTable *giop_objkey_hash = NULL; /* hash */
776 GMemChunk *giop_objkey_keys = NULL; /* key storage */
777 GMemChunk *giop_objkey_vals = NULL; /* val storage */
782 * ------------------------------------------------------------------------------------------+
783 * Private helper functions
784 * ------------------------------------------------------------------------------------------+
790 * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
793 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
794 GList * newlist_start;
795 comp_req_list_entry_t * entry = NULL;
798 entry = g_malloc(sizeof(comp_req_list_entry_t));
799 opn = g_strdup(op); /* duplicate operation for storage */
802 entry->reqid = reqid;
804 entry->operation = opn;
805 entry->repoid = NULL; /* dont have yet */
807 newlist_start = g_list_append (list, entry); /* append */
809 return newlist_start;
814 * Used to find an entry with matching Frame Number FN
815 * in the complete_request_list list.
818 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
820 GList * element; /* entry in list */
821 comp_req_list_entry_t * entry_ptr = NULL;
823 element = g_list_last(giop_complete_request_list); /* start from last */
825 while(element) { /* valid list entry */
826 entry_ptr = element->data; /* grab data pointer */
827 if (entry_ptr->fn == fn) { /* similar FN */
830 element = g_list_previous(element); /* try next previous */
833 return NULL; /* no match so return NULL */
838 * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
840 * Call this when you know a FN and matching giop_sub_handle_t and repoid
842 * This is done in say, try_explicit_dissector for example.
846 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
848 comp_req_list_entry_t * entry = NULL;
849 entry = find_fn_in_list(fn); /* grab FN data entry */
853 entry->repoid = g_strdup(repoid); /* copy and store */
861 /* giop_complete_reply_hash "EQUAL" Functions */
863 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
864 struct complete_reply_hash_key *mk1 = (struct complete_reply_hash_key *)v;
865 struct complete_reply_hash_key *mk2 = (struct complete_reply_hash_key *)w;
867 if (mk1->fn == mk2->fn) {
871 return 0; /* found differences */
874 /* giop_complete_reply_hash "HASH" Functions */
876 static guint32 complete_reply_hash_fn(gconstpointer v) {
877 guint32 val; /* init hash value */
878 struct complete_reply_hash_key *key = (struct complete_reply_hash_key *)v;
880 val = key->fn; /* simple and unique */
887 * Insert the FN and MFN together in our complete_reply_hash.
890 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
892 struct complete_reply_hash_key key, *new_key;
893 struct complete_reply_hash_val *val = NULL;
897 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
900 return; /* FN collision */
903 new_key = g_mem_chunk_alloc(giop_complete_reply_keys);
904 new_key->fn = fn; /* save FN */
906 val = g_mem_chunk_alloc(giop_complete_reply_vals);
907 val->mfn = mfn; /* and MFN */
909 g_hash_table_insert(giop_complete_reply_hash, new_key, val);
914 * Find the MFN values from a given FN key.
915 * Assumes the complete_reply_hash is already populated.
918 static guint32 get_mfn_from_fn(guint32 fn) {
920 struct complete_reply_hash_key key;
921 struct complete_reply_hash_val *val = NULL;
922 guint32 mfn = fn; /* save */
925 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
928 mfn = val->mfn; /* grab it */
931 return mfn; /* mfn or fn if not found */
936 * Attempt to find the MFN for this FN, and return it.
937 * Return MFN if found, or just FN if not. This is
938 * only used when we are building
941 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
943 GList * element; /* last entry in list */
944 comp_req_list_entry_t * entry_ptr = NULL;
946 /* Need Some pretty snappy code */
948 /* Loop back from current end of complete_request_list looking for */
949 /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
952 * As this routine is only called during initial pass of data,
953 * and NOT when a user clicks, it is ok to start from Current
954 * end of complete_request_list when searching for a match.
955 * As that list is bing populated in the same order as FN's
958 * Also, can make check for same reqid more detailed, but I start
959 * with reqid. Could add say port or address checks etc later ??
963 element = g_list_last(giop_complete_request_list); /* get last */
965 while(element) { /* valid list entry */
966 entry_ptr = element->data; /* grab data pointer */
967 if (entry_ptr->reqid == reqid) { /* similar reqid */
968 return entry_ptr->fn; /* return MFN */
970 element = g_list_previous(element); /* try next previous */
973 return fn; /* no match so return FN */
977 /* Module Hash "EQUAL" Functions */
979 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
980 struct giop_module_key *mk1 = (struct giop_module_key *)v;
981 struct giop_module_key *mk2 = (struct giop_module_key *)w;
983 if (!strcmp(mk1->module, mk2->module)) {
987 return 0; /* found differences */
990 /* Module Hash "HASH" Functions */
992 static guint32 giop_hash_module_hash(gconstpointer v) {
995 guint32 val = 0; /* init hash value */
997 struct giop_module_key *key = (struct giop_module_key *)v;
1000 * Hmm, try this simple hashing scheme for now.
1001 * ie: Simple summation, FIX later -- FS
1006 len = strlen(key->module);
1008 for (i=0; i<len; i++) {
1009 val += (guint8) key->module[i];
1018 * ------------------------------------------------------------------------------------------+
1019 * Public Utility functions
1020 * ------------------------------------------------------------------------------------------+
1027 * Routine to allow giop users to register their sub dissector function, name, and
1028 * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1029 * value returned from their proto_register_protocol(), so we can enable/disbale it
1030 * through the GUI (edit protocols).
1032 * This is used by try_explicit_giop_dissector() to find the
1033 * correct sub-dissector.
1037 void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
1039 struct giop_module_key module_key, *new_module_key;
1040 struct giop_module_val *module_val = NULL;
1042 module_key.module = module; /* module name */
1044 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1047 return; /* module name collision */
1050 /* So, passed module name should NOT exist in hash at this point.*/
1053 printf("giop:register_module: Adding Module %s to module hash \n", module);
1054 printf("giop:register_module: Module sub dissector name is %s \n", name);
1057 new_module_key = g_mem_chunk_alloc(giop_module_keys);
1058 new_module_key->module = module; /* save Module or interface name from IDL */
1060 module_val = g_mem_chunk_alloc(giop_module_vals);
1062 module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
1064 module_val->subh->sub_name = name; /* save dissector name */
1065 module_val->subh->sub_fn = sub; /* save subdissector*/
1066 module_val->subh->sub_proto = sub_proto; /* save subdissector's proto_XXX value */
1068 g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1075 /* Object Key Hash "EQUAL" Functions */
1077 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1078 struct giop_object_key *v1 = (struct giop_object_key *)v;
1079 struct giop_object_key *v2 = (struct giop_object_key *)w;
1081 if (v1->objkey_len != v2->objkey_len)
1082 return 0; /* no match because different length */
1084 /* Now do a byte comaprison */
1086 if (!memcmp(v1->objkey,v2->objkey, v1->objkey_len)) {
1087 return 1; /* compares ok */
1091 printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1094 return 0; /* found differences */
1097 /* Object Key Hash "HASH" Functions */
1099 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1100 struct giop_object_key *key = (struct giop_object_key *)v;
1103 guint32 val = 0; /* init hash value */
1107 * Hmm, try this simple hashing scheme for now.
1108 * ie: Simple summation
1114 printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1117 for (i=0; i< key->objkey_len; i++) {
1118 val += (guint8) key->objkey[i];
1126 * Routine to take an object key octet sequence, and length, and ptr to
1127 * a (null terminated )repository ID string, and store them in the obect key hash.
1129 * Blindly Inserts even if it does exist, See TODO at top for reason.
1132 static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
1134 struct giop_object_key objkey_key, *new_objkey_key;
1135 struct giop_object_val *objkey_val = NULL;
1137 objkey_key.objkey_len = len; /* length */
1138 objkey_key.objkey = obj; /* object key octet sequence */
1140 /* Look it up to see if it exists */
1142 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1144 /* CHANGED -- Same reqid, so abandon old entry */
1147 g_hash_table_remove(hash, &objkey_key);
1150 /* So, passed key should NOT exist in hash at this point.*/
1152 new_objkey_key = g_mem_chunk_alloc(giop_objkey_keys);
1153 new_objkey_key->objkey_len = len; /* save it */
1154 new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */
1156 objkey_val = g_mem_chunk_alloc(giop_objkey_vals);
1157 objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
1158 objkey_val->src = src; /* where IOR came from */
1162 printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
1163 objkey_val->repo_id, new_objkey_key->objkey_len);
1166 g_hash_table_insert(hash, new_objkey_key, objkey_val);
1173 * convert an ascii char representing a hex value,
1174 * to a numeric value.
1176 * returns value, or -1 if problem.
1180 static gint8 hex_char_to_val(guchar c){
1187 retval = c - 48; /* convert digit */
1191 c = toupper(c); /* convert to uppercase */
1192 if (c >= 'A' && c <= 'F') {
1203 * Convert from stringified IOR of the kind IOR:af4f7e459f....
1204 * to an IOR octet sequence.
1206 * User must free buffer.
1208 * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1209 * grab repoid etc for our objkey hash.
1213 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1216 gint8 tmpval; /* complete value */
1219 *out = g_new0(guint8, in_len); /* allocate buffer */
1225 /* skip past IOR: and convert character pairs to guint8 */
1227 for (i=4; i<in_len-1; i+=2) {
1228 if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1230 if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1231 g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1235 if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1236 g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1239 tmpval = tmpval_msb << 4;
1240 tmpval += tmpval_lsb;
1241 (*out)[(i-4)/2] = (guint8) tmpval;
1251 return (i-4)/2; /* length */
1258 * Simple getline, copied from somewhere :)
1262 static int getline(FILE *fp, gchar *line, int maxlen) {
1264 if (fgets(line,maxlen,fp) == NULL)
1267 return strlen(line);
1273 * Read a list of stringified IOR's from a named file, convert to IOR's
1274 * and store in object key hash
1277 static void read_IOR_strings_from_file(gchar *name, int max_iorlen) {
1278 guchar *buf; /* NOTE reused for every line */
1280 int ior_val_len; /* length after unstringifying. */
1282 guint8 *out; /* ptr to unstringified IOR */
1283 tvbuff_t *tvb; /* temp tvbuff for dissectin IORs */
1284 guint32 my_offset = 0;
1285 gboolean stream_is_big_endian;
1288 fp = fopen(name,"r"); /* open read only */
1291 if (errno == EACCES)
1292 fprintf(stderr, "Error opening file IOR.txt for reading: %s\n",strerror(errno));
1296 buf = g_malloc0(max_iorlen+1); /* input buf */
1298 while ((len = getline(fp,buf,max_iorlen+1)) > 0) {
1299 my_offset = 0; /* reset for every IOR read */
1301 ior_val_len = string_to_IOR(buf,len,&out); /* convert */
1305 /* Combination of tvb_new() and tvb_set_real_data().
1306 Can throw ReportedBoundsError.
1308 XXX - can it throw an exception in this case? If so, we
1309 need to catch it and clean up, but we really shouldn't allow
1310 it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
1313 tvb = tvb_new_real_data(out,ior_val_len,ior_val_len, "GIOP FILE IOR");
1315 stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1316 decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1326 fclose(fp); /* be nice */
1334 * Init routine, setup our request hash stuff, or delete old ref's
1336 * Cannot setup the module hash here as my init() may not be called before
1337 * users start registering. So I will move the module_hash stuff to
1338 * proto_register_giop, as is done with packet-rpc
1342 * Also, setup our objectkey/repoid hash here.
1346 static void giop_init(void) {
1350 * Create objkey/repoid hash, use my "equal" and "hash" functions.
1354 if (giop_objkey_hash)
1355 g_hash_table_destroy(giop_objkey_hash);
1356 if (giop_objkey_keys)
1357 g_mem_chunk_destroy(giop_objkey_keys);
1358 if (giop_objkey_vals)
1359 g_mem_chunk_destroy(giop_objkey_vals);
1363 * Create hash, use my "equal" and "hash" functions.
1367 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1369 giop_objkey_keys = g_mem_chunk_new("giop_objkey_keys",
1370 sizeof(struct giop_object_key),
1371 giop_objkey_init_count * sizeof(struct giop_object_key),
1374 giop_objkey_vals = g_mem_chunk_new("giop_objkey_vals",
1375 sizeof(struct giop_object_val),
1376 giop_objkey_init_count * sizeof(struct giop_object_val),
1381 * Create complete_reply_hash, use my "equal" and "hash" functions.
1385 if (giop_complete_reply_hash)
1386 g_hash_table_destroy(giop_complete_reply_hash);
1387 if (giop_complete_reply_keys)
1388 g_mem_chunk_destroy(giop_complete_reply_keys);
1389 if (giop_complete_reply_vals)
1390 g_mem_chunk_destroy(giop_complete_reply_vals);
1394 * Create hash, use my "equal" and "hash" functions.
1398 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1400 giop_complete_reply_keys = g_mem_chunk_new("giop_complete_reply_keys",
1401 sizeof(struct complete_reply_hash_key),
1402 complete_reply_hash_count * sizeof(struct complete_reply_hash_key),
1405 giop_complete_reply_vals = g_mem_chunk_new("giop_complete_reply_vals",
1406 sizeof(struct complete_reply_hash_val),
1407 complete_reply_hash_count * sizeof(struct complete_reply_hash_val),
1412 read_IOR_strings_from_file("IOR.txt", 600); /* testing */
1419 * Insert an entry in the GIOP Heuristic User table.
1421 * Uses giop_sub_handle_t to wrap giop user info.
1425 void register_giop_user(giop_sub_dissector_t *sub, gchar *name, int sub_proto) {
1427 giop_sub_handle_t *subh;
1429 subh = g_malloc(sizeof (giop_sub_handle_t));
1431 subh->sub_name = name;
1433 subh->sub_proto = sub_proto; /* proto_XXX from sub dissectors's proto_register_protocol() */
1435 giop_sub_list = g_slist_append (giop_sub_list, subh);
1441 * Lookup an object key in our object key hash, and return the corresponding
1446 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1448 struct giop_object_key objkey_key;
1449 struct giop_object_val *objkey_val = NULL;
1451 objkey_key.objkey_len = len; /* length */
1452 objkey_key.objkey = obj; /* object key octet sequence */
1454 /* Look it up to see if it exists */
1456 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1460 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1462 return objkey_val->repo_id; /* found */
1466 printf("FAILED Lookup of object key \n" );
1469 return NULL; /* not found */
1475 * Extract top level module/interface from repoid
1477 * eg from - "IDL:Echo/interface1:1.0"
1480 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1481 * get linux.org/Penguin/Teeth
1484 * User must free returned ptr after use.
1486 * TODO -- generalize for other Repoid encodings
1489 static gchar * get_modname_from_repoid(gchar *repoid) {
1491 gchar *modname = NULL;
1492 gchar *saved_repoid = NULL;
1494 guint8 stop_mod; /* Index of last character of modname in Repoid */
1495 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1498 saved_repoid = g_strdup(repoid); /* make a copy */
1500 /* Must start with IDL: , otherwise I get confused */
1502 if (g_strncasecmp("IDL:",repoid,4))
1505 /* Looks like a RepoID to me, so get Module or interface name */
1507 /* TODO -- put some code here to get Module name */
1509 for(i=4; c != '\0'; i++) {
1511 stop_mod = i; /* save */
1512 if (c == ':' ) /* delimiters */
1517 /* Now create a new string based on start and stop and \0 */
1519 modname = g_strndup(repoid+4, stop_mod - start_mod);
1534 * Display a "module" hash entry
1537 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1539 struct giop_module_val *mv = (struct giop_module_val *) val;
1540 struct giop_module_key *mk = (struct giop_module_key *) key;
1542 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1549 * Display a "complete_reply " hash entry
1552 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1554 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1555 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1557 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1565 * Display an "objkey" hash entry
1568 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1570 struct giop_object_val *mv = (struct giop_object_val *) val;
1571 struct giop_object_key *mk = (struct giop_object_key *) key;
1574 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1576 for (i=0; i<mk->objkey_len; i++) {
1577 printf("%.2x ", mk->objkey[i]);
1581 * If read from file, mark it as such..
1585 printf(", Repo ID = %s \n", mv->repo_id);
1588 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1596 * Display all giop_sub_list (GSList) entries
1599 static void display_heuristic_user_list() {
1602 giop_sub_handle_t *subh; /* handle */
1604 /* Get length of list */
1605 len = g_slist_length(giop_sub_list); /* find length */
1610 for (i=0; i<len; i++) {
1611 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1612 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1618 * Display all complete_request_list (GList) entries
1621 static void display_complete_request_list() {
1624 comp_req_list_entry_t *entry;
1626 /* Get length of list */
1627 len = g_list_length(giop_complete_request_list); /* find length */
1632 for (i=0; i<len; i++) {
1633 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1634 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1635 entry->reqid,entry->operation, entry->repoid);
1643 /* Dump Hash/List contents
1645 * collection_type specifies the list or hash to dump
1649 static void giop_dump_collection(collection_data_t collection_type) {
1651 switch(collection_type) {
1652 case cd_heuristic_users:
1653 printf("+----------------------------------------------+ \n");
1654 printf("+-------------- Heuristic User (Begin) --------+ \n");
1655 printf("+----------------------------------------------+ \n");
1657 display_heuristic_user_list();
1659 printf("+----------------------------------------------+ \n");
1660 printf("+-------------- Heuristic User (End) ----------+ \n");
1661 printf("+----------------------------------------------+ \n");
1665 case cd_complete_request_list:
1666 printf("+----------------------------------------------+ \n");
1667 printf("+------------- Complete Request List (Begin) --+ \n");
1668 printf("+----------------------------------------------+ \n");
1670 display_complete_request_list();
1672 printf("+----------------------------------------------+ \n");
1673 printf("+------------ Complete Request List (End) -----+ \n");
1674 printf("+----------------------------------------------+ \n");
1678 case cd_module_hash:
1679 printf("+----------------------------------------------+ \n");
1680 printf("+-------------- Module (Begin) ----------------+ \n");
1681 printf("+----------------------------------------------+ \n");
1683 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1685 printf("+----------------------------------------------+ \n");
1686 printf("+-------------- Module ( End) -----------------+ \n");
1687 printf("+----------------------------------------------+ \n\n");
1691 case cd_objkey_hash:
1692 printf("+----------------------------------------------+ \n");
1693 printf("+-------------- Objkey (Begin) ----------------+ \n");
1694 printf("+----------------------------------------------+ \n");
1696 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1698 printf("+----------------------------------------------+ \n");
1699 printf("+-------------- Objkey (End) ------------------+ \n");
1700 printf("+----------------------------------------------+ \n\n");
1704 case cd_complete_reply_hash:
1705 printf("+----------------------------------------------+ \n");
1706 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1707 printf("+----------------------------------------------+ \n");
1709 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1711 printf("+----------------------------------------------+ \n");
1712 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1713 printf("+----------------------------------------------+ \n");
1719 printf("giop: giop_dump_collection: Unknown type \n");
1730 * Loop through all subdissectors, and call them until someone
1731 * answers (returns TRUE). This function then returns TRUE, otherwise
1734 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1737 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1738 MessageHeader *header, gchar *operation ) {
1741 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1742 giop_sub_handle_t *subh = NULL;
1744 len = g_slist_length(giop_sub_list); /* find length */
1749 for (i=0; i<len; i++) {
1750 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1752 if (proto_is_protocol_enabled(subh->sub_proto)) {
1753 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1755 return TRUE; /* found one, lets return */
1757 } /* protocol_is_enabled */
1760 return res; /* result */
1766 * Find the matching repoid in the module hash and call
1767 * the dissector function if offset exists.
1770 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1771 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1777 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1778 MessageHeader *header, gchar *operation, gchar *repoid ) {
1780 giop_sub_handle_t *subdiss = NULL; /* handle */
1781 gboolean res = FALSE;
1782 gchar *modname = NULL;
1783 struct giop_module_key module_key;
1784 struct giop_module_val *module_val = NULL;
1788 * Get top level module/interface from complete repoid
1791 modname = get_modname_from_repoid(repoid);
1792 if (modname == NULL) {
1793 return res; /* unknown module name */
1797 /* Search for Module or interface name */
1799 module_key.module = modname; /* module name */
1800 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1802 if (module_val == NULL) {
1803 return res; /* module not registered */
1806 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1809 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1810 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1811 /* but only if user not clicking */
1813 if (!pinfo->fd->flags.visited)
1814 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1817 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1819 if (tvb_offset_exists(tvb, *offset)) {
1821 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1824 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1826 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1828 } /* protocol_is_enabled */
1829 } /* offset exists */
1832 return res; /* return result */
1837 /* Take in an array of char and create a new string.
1838 * Replace non-printable characters with periods.
1840 * The array may contain \0's so dont use strdup
1841 * The string is \0 terminated, and thus longer than
1842 * the initial sequence.
1843 * Caller must free the new string.
1846 static gchar * make_printable_string (gchar *in, guint32 len) {
1848 gchar *print_string = NULL;
1850 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1851 memcpy(print_string, in, len); /* and make a copy of input data */
1853 for(i=0; i < len; i++) {
1854 if( !isprint( (unsigned char)print_string[i] ) )
1855 print_string[i] = '.';
1858 return print_string; /* return ptr */
1861 /* Determine the byte order from the GIOP MessageHeader */
1863 gboolean is_big_endian (MessageHeader * header) {
1864 gboolean big_endian = FALSE;
1866 switch (header->GIOP_version.minor) {
1869 if (header->flags & 0x01)
1889 * Calculate new offset, based on the current offset, and user supplied
1890 * "offset delta" value, and the alignment requirement.
1894 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1895 * aligned on 8 byte boundaries.
1898 static void set_new_alignment(int *offset, int delta, int alignment) {
1900 while( ( (*offset + delta) % alignment) != 0)
1909 * ------------------------------------------------------------------------------------------+
1910 * Public get_CDR_xxx functions.
1911 * ------------------------------------------------------------------------------------------+
1917 * Gets data of type any. This is encoded as a TypeCode
1918 * followed by the encoded value.
1921 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1922 gboolean stream_is_big_endian, int boundary,
1923 MessageHeader * header ) {
1925 guint32 TCKind; /* TypeCode */
1927 /* get TypeCode of any */
1928 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1930 /* dissect data of type TCKind */
1931 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1935 /* Copy a 1 octet sequence from the tvbuff
1936 * which represents a boolean value, and convert
1937 * it to a boolean value.
1938 * Offset is then incremented by 1, to indicate the 1 octet which
1939 * has been processed.
1942 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1945 val = tvb_get_guint8(tvb, *offset); /* easy */
1950 /* Copy a 1 octet sequence from the tvbuff
1951 * which represents a char, and convert
1952 * it to an char value.
1953 * offset is then incremented by 1, to indicate the 1 octet which
1954 * has been processed.
1957 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1960 val = tvb_get_guint8(tvb, *offset); /* easy */
1968 * Floating Point Data Type double IEEE 754-1985
1970 * Copy an 8 octet sequence from the tvbuff
1971 * which represents a double value, and convert
1972 * it to a double value, taking into account byte order.
1973 * offset is first incremented so that it falls on a proper alignment
1974 * boundary for double values.
1975 * offset is then incremented by 8, to indicate the 8 octets which
1976 * have been processed.
1979 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1982 guint8 e1,e2,f1,f2,f3,f4,f5,f6,f7;
1985 guint32 fract0, fract1;
1989 /* double values must be aligned on a 8 byte boundary */
1991 while( ( (*offset + boundary) % 8) != 0)
1995 if(stream_is_big_endian) {
1996 e1 = get_CDR_octet(tvb,offset);
1997 sign = e1 >> 7; /* sign value */
1998 e1 &= 0x7f; /* bottom 7 bits */
1999 f1 = get_CDR_octet(tvb,offset);
2001 f1 &= 0x0f; /* bottom 4 bits */
2002 f2 = get_CDR_octet(tvb,offset);
2003 f3 = get_CDR_octet(tvb,offset);
2004 f4 = get_CDR_octet(tvb,offset);
2005 f5 = get_CDR_octet(tvb,offset);
2006 f6 = get_CDR_octet(tvb,offset);
2007 f7 = get_CDR_octet(tvb,offset);
2011 f7 = get_CDR_octet(tvb,offset);
2012 f6 = get_CDR_octet(tvb,offset);
2013 f5 = get_CDR_octet(tvb,offset);
2014 f4 = get_CDR_octet(tvb,offset);
2015 f3 = get_CDR_octet(tvb,offset);
2016 f2 = get_CDR_octet(tvb,offset);
2017 f1 = get_CDR_octet(tvb,offset);
2019 f1 &= 0x0f; /* bottom 4 bits */
2020 e1 = get_CDR_octet(tvb,offset);
2021 sign = e1 >> 7; /* sign value */
2022 e1 &= 0x7f; /* bottom 7 bits */
2026 exp = (e1 << 4) + e2;
2028 /* Now lets do some 52 bit math with 32 bit constraint */
2030 fract0 = f7 + (f6 << 8) + (f5 << 16) + (f4 << 24); /* lower 32 bits of fractional part */
2031 fract1 = f3 + (f2 << 8) + (f1 << 16); /* top 20 bits of fractional part */
2033 d_fract = (fract1 / (pow(2,20))) + (fract0 / (pow(2,52))); /* 52 bits represent a fraction */
2035 val = pow(-1,sign) * pow(2,(exp - 1023)) * (1 + d_fract);
2037 return val; /* FIX rounding ?? */
2042 /* Copy a 4 octet sequence from the tvbuff
2043 * which represents an enum value, and convert
2044 * it to an enum value, taking into account byte order.
2045 * offset is first incremented so that it falls on a proper alignment
2046 * boundary for an enum (4)
2047 * offset is then incremented by 4, to indicate the 4 octets which
2048 * have been processed.
2050 * Enum values are encoded as unsigned long.
2054 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2056 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2062 * Copy an octet sequence from the tvbuff
2063 * which represents a Fixed point decimal type, and create a string representing
2064 * a Fixed point decimal type. There are no alignment restrictions.
2065 * Size and scale of fixed decimal type is determined by IDL.
2067 * digits - IDL specified number of "digits" for this fixed type
2068 * scale - IDL specified "scale" for this fixed type
2071 * eg: typedef fixed <5,2> fixed_t;
2072 * could represent numbers like 123.45, 789.12,
2075 * As the fixed type could be any size, I will not try to fit it into our
2076 * simple types like gdouble or glong etc. I will just create a string buffer holding
2077 * a representation (after scale is applied), and with a decimal point or zero padding
2078 * inserted at the right place if necessary. The string is null terminated
2080 * so string may look like
2083 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2085 * According to spec, digits <= 31
2086 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2089 * User must remember to free the buffer
2094 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2096 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2097 guint32 i ; /* loop */
2098 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2099 /* this does not include sign, decimal point and \0 */
2100 guint32 sindex = 0; /* string index */
2101 gchar *tmpbuf; /* temp buff, holds string without scaling */
2102 guint8 tval; /* temp val storage */
2105 * how many bytes to hold digits and scale (if scale <0)
2107 * eg: fixed <5,2> = 5 digits
2108 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2112 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2116 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2118 slen = digits; /* digits */
2122 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2125 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2128 * Register a cleanup function in case on of our tvbuff accesses
2129 * throws an exception. We need to clean up tmpbuf.
2131 CLEANUP_PUSH(g_free, tmpbuf);
2133 /* If even , grab 1st dig */
2135 if (!(digits & 0x01)) {
2136 tval = get_CDR_octet(tvb,offset);
2138 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2140 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2145 * Loop, but stop BEFORE we hit last digit and sign
2146 * if digits = 1 or 2, then this part is skipped
2150 for(i=0; i< ((digits-1)/2 ); i++) {
2151 tval = get_CDR_octet(tvb,offset);
2153 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2156 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2158 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2165 printf("giop:get_CDR_fixed(): before last digit \n");
2169 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2171 tval = get_CDR_octet(tvb,offset);
2173 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2175 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2178 sign = tval & 0x0f; /* get sign */
2180 /* So now, we have all digits in an array, and the sign byte
2181 * so lets generate a printable string, taking into account the scale
2185 sindex = 0; /* reset */
2186 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2187 * \0 -- TODO check slen is reasonable first */
2189 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2194 (*seq)[sindex] = '+'; /* put sign in first string position */
2197 (*seq)[sindex] = '-';
2200 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2201 (*seq)[sindex] = '*'; /* flag as sign unkown */
2207 /* Add decimal point or padding 0's, depending if scale is positive or
2208 * negative, respectively
2212 for (i=0; i<digits-scale; i++) {
2213 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2217 (*seq)[sindex] = '.'; /* decimal point */
2220 for (i=digits-scale; i<digits; i++) {
2221 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2225 (*seq)[sindex] = '\0'; /* string terminator */
2229 /* negative scale, dump digits and pad out with 0's */
2231 for (i=0; i<digits-scale; i++) {
2233 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2235 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2240 (*seq)[sindex] = '\0'; /* string terminator */
2245 * We're done with tmpbuf, so we can call the cleanup handler to free
2246 * it, and then pop the cleanup handler.
2248 CLEANUP_CALL_AND_POP;
2251 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2261 * Floating Point Data Type float IEEE 754-1985
2263 * Copy an 4 octet sequence from the tvbuff
2264 * which represents a float value, and convert
2265 * it to a float value, taking into account byte order.
2266 * offset is first incremented so that it falls on a proper alignment
2267 * boundary for float values.
2268 * offset is then incremented by 4, to indicate the 4 octets which
2269 * have been processed.
2272 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2275 guint8 e1,e2,f1,f2,f3;
2281 /* float values must be aligned on a 4 byte boundary */
2283 while( ( (*offset + boundary) % 4) != 0)
2286 if(stream_is_big_endian) {
2287 e1 = get_CDR_octet(tvb,offset);
2288 sign = e1 >> 7; /* sign value */
2289 e1 &= 0x7f; /* bottom 7 bits */
2290 f1 = get_CDR_octet(tvb,offset);
2292 f1 &= 0x7f; /* bottom 7 bits */
2293 f2 = get_CDR_octet(tvb,offset);
2294 f3 = get_CDR_octet(tvb,offset);
2298 f3 = get_CDR_octet(tvb,offset);
2299 f2 = get_CDR_octet(tvb,offset);
2300 f1 = get_CDR_octet(tvb,offset);
2302 f1 &= 0x7f; /* bottom 7 bits */
2303 e1 = get_CDR_octet(tvb,offset);
2304 sign = e1 >> 7; /* sign value */
2305 e1 &= 0x7f; /* bottom 7 bits */
2310 exp = (e1 << 1) + e2;
2311 fract = f3 + (f2 << 8) + (f1 << 16);
2313 d_fract = fract / (pow(2,23)); /* 23 bits represent a fraction */
2315 val = pow(-1,sign) * pow(2,(exp - 127)) * (1 + d_fract);
2317 return val; /* FIX rounding ?? */
2323 * Decode an Interface type, and display it on the tree.
2326 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2327 gboolean stream_is_big_endian, int boundary) {
2330 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2336 /* Copy a 4 octet sequence from the tvbuff
2337 * which represents a signed long value, and convert
2338 * it to an signed long vaule, taking into account byte order.
2339 * offset is first incremented so that it falls on a proper alignment
2340 * boundary for long values.
2341 * offset is then incremented by 4, to indicate the 4 octets which
2342 * have been processed.
2345 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2349 /* unsigned long values must be aligned on a 4 byte boundary */
2350 while( ( (*offset + boundary) % 4) != 0)
2353 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2354 tvb_get_letohl (tvb, *offset);
2361 * Decode an Object type, and display it on the tree.
2364 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2365 gboolean stream_is_big_endian, int boundary) {
2367 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2373 /* Copy a 1 octet sequence from the tvbuff
2374 * which represents a octet, and convert
2375 * it to an octet value.
2376 * offset is then incremented by 1, to indicate the 1 octet which
2377 * has been processed.
2380 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2383 val = tvb_get_guint8(tvb, *offset); /* easy */
2389 /* Copy a sequence of octets from the tvbuff.
2390 * Caller of this function must remember to free the
2391 * array pointed to by seq.
2392 * This function also increments offset by len.
2395 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, int len) {
2397 if (! tvb_bytes_exist(tvb, *offset,len)) {
2399 * Generate an exception, and stop processing.
2400 * We do that now, rather than after allocating the buffer, so we
2401 * don't have to worry about freeing the buffer.
2402 * XXX - would we be better off using a cleanup routine?
2404 tvb_get_guint8(tvb, *offset + len);
2408 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2409 * do what we do now, and null-terminate the string (which also means
2410 * we don't need to zero out the entire allocation, just the last byte)?
2412 *seq = g_new0(gchar, len + 1);
2413 tvb_memcpy( tvb, *seq, *offset, len);
2418 /* Copy a 2 octet sequence from the tvbuff
2419 * which represents a signed short value, and convert
2420 * it to a signed short value, taking into account byte order.
2421 * offset is first incremented so that it falls on a proper alignment
2422 * boundary for short values.
2423 * offset is then incremented by 2, to indicate the 2 octets which
2424 * have been processed.
2427 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2431 /* short values must be aligned on a 2 byte boundary */
2432 while( ( (*offset + boundary) % 2) != 0)
2435 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2436 tvb_get_letohs (tvb, *offset);
2444 /* Copy an octet sequence from the tvbuff
2445 * which represents a string, and convert
2446 * it to an string value, taking into account byte order.
2447 * offset is first incremented so that it falls on a proper alignment
2448 * boundary for string values. (begins with an unsigned long LI)
2450 * String sequence is copied to a buffer "seq". This must
2451 * be freed by the calling program.
2452 * offset is then incremented, to indicate the octets which
2453 * have been processed.
2455 * returns number of octets in the sequence
2457 * Note: This function only supports single byte encoding at the
2458 * moment until I get a handle on multibyte encoding etc.
2463 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2468 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2471 (*offset)++; /* must step past \0 delimiter */
2475 get_CDR_octet_seq(tvb, seq, offset, slength);
2477 *seq = g_strdup(""); /* zero-length string */
2480 return slength; /* return length */
2484 /* Process a sequence of octets that represent the
2485 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2487 * This function also increments offset to the correct position.
2489 * It will parse the TypeCode and output data to the "tree" provided
2492 * It returns a guint32 representing a TCKind value.
2495 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2496 gboolean stream_is_big_endian, int boundary,
2497 MessageHeader * header ) {
2500 gint16 s_octet2; /* signed int16 */
2501 guint16 u_octet2; /* unsigned int16 */
2502 guint32 u_octet4; /* unsigned int32 */
2504 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2506 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2507 *offset-sizeof(val),4,val);
2510 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2513 case tk_null: /* empty parameter list */
2515 case tk_void: /* empty parameter list */
2517 case tk_short: /* empty parameter list */
2519 case tk_long: /* empty parameter list */
2521 case tk_ushort: /* empty parameter list */
2523 case tk_ulong: /* empty parameter list */
2525 case tk_float: /* empty parameter list */
2527 case tk_double: /* empty parameter list */
2529 case tk_boolean: /* empty parameter list */
2531 case tk_char: /* empty parameter list */
2533 case tk_octet: /* empty parameter list */
2535 case tk_any: /* empty parameter list */
2537 case tk_TypeCode: /* empty parameter list */
2539 case tk_Principal: /* empty parameter list */
2541 case tk_objref: /* complex parameter list */
2542 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2544 case tk_struct: /* complex parameter list */
2545 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2547 case tk_union: /* complex parameter list */
2548 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2550 case tk_enum: /* complex parameter list */
2551 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2554 case tk_string: /* simple parameter list */
2555 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2557 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2558 *offset-sizeof(u_octet4),4,u_octet4);
2562 case tk_sequence: /* complex parameter list */
2563 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2565 case tk_array: /* complex parameter list */
2566 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2568 case tk_alias: /* complex parameter list */
2569 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2571 case tk_except: /* complex parameter list */
2572 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2574 case tk_longlong: /* empty parameter list */
2576 case tk_ulonglong: /* empty parameter list */
2578 case tk_longdouble: /* empty parameter list */
2580 case tk_wchar: /* empty parameter list */
2582 case tk_wstring: /* simple parameter list */
2583 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2585 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2586 *offset-sizeof(u_octet4),4,u_octet4);
2590 case tk_fixed: /* simple parameter list */
2591 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2593 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2594 *offset-sizeof(u_octet2),2,u_octet2);
2597 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2599 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2600 *offset-sizeof(s_octet2),2,s_octet2);
2604 case tk_value: /* complex parameter list */
2605 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2607 case tk_value_box: /* complex parameter list */
2608 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2610 case tk_native: /* complex parameter list */
2611 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2613 case tk_abstract_interface: /* complex parameter list */
2614 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2617 g_warning("giop: Unknown TCKind %u \n", val);
2626 /* Copy a 4 octet sequence from the tvbuff
2627 * which represents an unsigned long value, and convert
2628 * it to an unsigned long vaule, taking into account byte order.
2629 * offset is first incremented so that it falls on a proper alignment
2630 * boundary for unsigned long values.
2631 * offset is then incremented by 4, to indicate the 4 octets which
2632 * have been processed.
2635 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2639 /* unsigned long values must be aligned on a 4 byte boundary */
2640 while( ( (*offset + boundary) % 4) != 0)
2643 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2644 tvb_get_letohl (tvb, *offset);
2651 /* Copy a 2 octet sequence from the tvbuff
2652 * which represents an unsigned short value, and convert
2653 * it to an unsigned short value, taking into account byte order.
2654 * offset is first incremented so that it falls on a proper alignment
2655 * boundary for unsigned short values.
2656 * offset is then incremented by 2, to indicate the 2 octets which
2657 * have been processed.
2660 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2664 /* unsigned short values must be aligned on a 2 byte boundary */
2665 while( ( (*offset + boundary) % 2) != 0)
2668 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2669 tvb_get_letohs (tvb, *offset);
2677 /* Copy a wchar from the tvbuff.
2678 * Caller of this function must remember to free the
2679 * array pointed to by seq.
2680 * This function also increments offset according to
2683 * For GIOP 1.1 read 2 octets and return size -2. The
2684 * negation means there is no size element in the packet
2685 * and therefore no size to add to the tree.
2687 * For GIOP 1.2 read size of wchar and the size
2688 * octets. size is returned as a gint8.
2690 * For both GIOP versions the wchar is returned
2691 * as a printable string.
2695 /* NOTE: This is very primitive in that it just reads
2696 * the wchar as a series of octets and returns them
2697 * to the user. No translation is attempted based on
2698 * byte orientation, nor on code set. I.e it only
2699 * really reads past the wchar and sets the offset
2703 /* The "decoding" is done according to CORBA chapter 15.
2704 * Wchar is not supported for GIOP 1.0.
2707 gint8 get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2712 /* CORBA chapter 15:
2713 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2714 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2715 * followed by the elements of the octet sequence representing
2716 * the encoded value of the wchar.
2719 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2720 slength = 2; /* set for GIOP 1.1 length in octets */
2722 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2723 slength = get_CDR_octet(tvb,offset);
2726 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2727 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2729 /* now turn octets (wchar) into something that can be printed by the user */
2730 *seq = make_printable_string(raw_wstring, slength);
2732 g_free(raw_wstring);
2735 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2736 if (header->GIOP_version.minor < 2)
2739 return slength; /* return length */
2744 /* Copy a wstring from the tvbuff.
2745 * Caller of this function must remember to free the
2746 * array pointed to by seq.
2747 * This function also increments offset, according to
2748 * wstring length. length is returned as guint32
2751 /* NOTE: This is very primitive in that it just reads
2752 * the wstring as a series of octets and returns them
2753 * to the user. No translation is attempted based on
2754 * byte orientation, nor on code set. I.e it only
2755 * really reads past the wstring and sets the offset
2759 /* The "decoding" is done according to CORBA chapter 15.
2760 * Wstring is not supported for GIOP 1.0.
2764 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2765 int boundary, MessageHeader * header) {
2770 /* CORBA chapter 15:
2771 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2772 * length and string are NUL terminated (length???).
2773 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2777 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2779 /* get length, same for all GIOP versions,
2780 * although for 1.2 CORBA doesnt say, so assume.
2782 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2786 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2787 slength = 5; /* better than core dumping during debug */
2791 if (header->GIOP_version.minor < 2) {
2793 (*offset)++; /* must step past \0 delimiter */
2795 /* assume length is number of characters and not octets, spec not clear */
2796 slength = slength * 2; /* length in octets is 2 * wstring length */
2800 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2802 /* now turn octets (wstring) into something that can be printed by the user */
2803 *seq = make_printable_string(raw_wstring, slength);
2805 g_free(raw_wstring);
2808 return slength; /* return length */
2815 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2817 * typedef short AddressingDisposition;
2818 * const short KeyAddr = 0;
2819 * const short ProfileAddr = 1;
2820 * const short ReferenceAddr = 2;
2821 * struct IORAddressingInfo {
2822 * unsigned long selected_profile_index;
2826 * union TargetAddress switch (AddressingDisposition) {
2827 * case KeyAddr: sequence <octet> object_key;
2828 * case ProfileAddr: IOP::TaggedProfile profile;
2829 * case ReferenceAddr: IORAddressingInfo ior;
2834 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2835 MessageHeader * header, gboolean stream_is_big_endian)
2837 guint16 discriminant;
2839 gchar *p_object_key;
2843 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2846 proto_tree_add_text (tree, tvb, *offset -2, 2,
2847 "TargetAddress Discriminant: %u", discriminant);
2850 switch (discriminant)
2852 case 0: /* KeyAddr */
2853 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2856 proto_tree_add_text (tree, tvb, *offset -4, 4,
2857 "KeyAddr (object key length): %u", len);
2862 get_CDR_octet_seq(tvb, &object_key, offset, len);
2863 p_object_key = make_printable_string( object_key, len );
2867 proto_tree_add_text (tree, tvb, *offset -len, len,
2868 "KeyAddr (object key): %s", p_object_key);
2870 g_free( p_object_key );
2871 g_free( object_key );
2874 case 1: /* ProfileAddr */
2875 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2876 stream_is_big_endian, NULL);
2878 case 2: /* ReferenceAddr */
2879 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2883 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2884 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2887 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2895 dissect_reply_body (tvbuff_t *tvb, u_int offset, packet_info *pinfo,
2896 proto_tree *tree, gboolean stream_is_big_endian,
2897 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2899 u_int sequence_length;
2900 gboolean exres = FALSE; /* result of trying explicit dissectors */
2901 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2904 * comp_req_list stuff
2907 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2911 switch (reply_status)
2913 case SYSTEM_EXCEPTION:
2915 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2918 case USER_EXCEPTION:
2920 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2924 proto_tree_add_text(tree, tvb, offset-4, 4,
2925 "Exception length: %u", sequence_length);
2927 if (sequence_length != 0)
2931 proto_tree_add_text(tree, tvb, offset, sequence_length,
2933 tvb_format_text(tvb, offset, sequence_length));
2937 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2939 /* read exception id from buffer and store in*/
2941 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2947 offset += sequence_length;
2953 * Now just fall through to the NO_EXCEPTION part
2954 * as this is common .
2962 /* lookup MFN in hash directly */
2964 mfn = get_mfn_from_fn(pinfo->fd->num);
2966 if (mfn == pinfo->fd->num)
2967 return; /* no matching frame number, what am I */
2969 /* get entry for this MFN */
2970 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2973 return; /* no matching entry */
2977 * If this packet is a REPLY to a RESOLVE(request)
2979 * TODO - make this lookup faster -- FS
2982 if (!strcmp(giop_op_resolve,entry->operation)) {
2983 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2987 /* TODO -- Put stuff here for other "interesting operations" */
2991 * Call sub dissector.
2992 * First try an find a explicit sub_dissector, then if that
2993 * fails, try the heuristic method.
2998 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
3001 /* Only call heuristic if no explicit dixxector was found */
3004 try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
3010 case LOCATION_FORWARD:
3011 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3015 case LOCATION_FORWARD_PERM:
3016 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3020 case NEEDS_ADDRESSING_MODE: {
3022 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3024 proto_tree_add_text (tree, tvb, offset -2, 2,
3025 "AddressingDisposition: %u", addr_disp);
3033 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
3039 g_free(repoid); /* free resource */
3049 /* The format of the Reply Header for GIOP 1.0 and 1.1
3050 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
3052 struct ReplyHeader_1_0 {
3053 IOP::ServiceContextList service_context;
3054 unsigned long request_id;
3055 ReplyStatusType_1_0 reply_status;
3059 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3060 proto_tree * clnp_tree, MessageHeader * header,
3061 gboolean stream_is_big_endian) {
3065 guint32 reply_status;
3066 proto_tree *reply_tree = NULL;
3068 guint32 mfn; /* matching frame number */
3071 tf = proto_tree_add_text (tree, tvb, offset,
3073 "General Inter-ORB Protocol Reply");
3074 if (reply_tree == NULL)
3076 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3082 * Decode IOP::ServiceContextList
3085 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3087 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3089 if (check_col(pinfo->cinfo, COL_INFO)) {
3090 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3094 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3095 "Request id: %u", request_id);
3098 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3100 if (check_col(pinfo->cinfo, COL_INFO)) {
3101 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3102 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3107 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3109 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3114 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3117 if (! pinfo->fd->flags.visited) {
3118 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3119 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3120 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3124 header->req_id = request_id; /* save for sub dissector */
3125 header->rep_status = reply_status; /* save for sub dissector */
3127 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3128 reply_status, header,tree);
3133 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3134 * and 1.1 header, only the fields have been rearranged. From Section
3135 * 15.4.3.1 of the CORBA 2.4 specification:
3137 * struct ReplyHeader_1_2 {
3138 * unsigned long request_id;
3139 * ReplyStatusType_1_2 reply_status;
3140 * IOP:ServiceContextList service_context;
3144 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3145 proto_tree * tree, proto_tree * clnp_tree,
3146 MessageHeader * header,
3147 gboolean stream_is_big_endian) {
3151 guint32 reply_status;
3152 proto_tree *reply_tree = NULL;
3154 guint32 mfn; /* matching frame number */
3157 tf = proto_tree_add_text (tree, tvb, offset,
3159 "General Inter-ORB Protocol Reply");
3160 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3163 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3165 if (check_col(pinfo->cinfo, COL_INFO)) {
3166 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3170 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3171 "Request id: %u", request_id);
3174 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3176 if (check_col(pinfo->cinfo, COL_INFO)) {
3177 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3178 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3183 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3185 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3190 * Decode IOP::ServiceContextList
3193 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3196 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3199 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3202 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3205 if (! pinfo->fd->flags.visited) {
3206 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3207 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3208 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3213 * Add header to argument list so sub dissector can get header info.
3216 header->req_id = request_id; /* save for sub dissector */
3217 header->rep_status = reply_status; /* save for sub dissector */
3219 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3220 reply_status,header,tree);
3226 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3227 proto_tree * tree, proto_tree * clnp_tree,
3228 MessageHeader * header, gboolean stream_is_big_endian) {
3232 proto_tree *cancel_request_tree = NULL;
3236 tf = proto_tree_add_text (tree, tvb, offset,
3238 "General Inter-ORB Protocol CancelRequest");
3239 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3242 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3244 if (check_col(pinfo->cinfo, COL_INFO)) {
3245 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3249 proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4,
3250 "Request id: %u", request_id);
3256 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3257 * in section 15.4.2.1 of the CORBA 2.4 specification.
3259 * struct RequestHeader{
3260 * IOP::ServiceContextList service_context;
3261 * unsigned long request_id;
3262 * boolean response_expected;
3263 * octet reserved[3]; // Only in GIOP 1.1
3264 * sequence<octet> object_key;
3266 * CORBA::OctetSeq requesting_principal;
3270 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3271 proto_tree * tree, proto_tree * clnp_tree,
3272 MessageHeader * header, gboolean stream_is_big_endian)
3278 guint32 objkey_len = 0; /* object key length */
3279 gchar *objkey = NULL; /* object key sequence */
3280 gchar *print_objkey; /* printable object key sequence */
3281 gboolean exres = FALSE; /* result of trying explicit dissectors */
3284 gchar *requesting_principal;
3285 gchar *print_requesting_principal;
3286 guint8 response_expected;
3288 proto_tree *request_tree = NULL;
3291 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3296 tf = proto_tree_add_text (tree, tvb, offset,
3298 "General Inter-ORB Protocol Request");
3299 if (request_tree == NULL)
3301 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3310 * Decode IOP::ServiceContextList
3313 decode_ServiceContextList(tvb, pinfo, request_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3316 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3317 if (check_col(pinfo->cinfo, COL_INFO))
3319 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3323 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3324 "Request id: %u", request_id);
3327 response_expected = tvb_get_guint8( tvb, offset );
3329 if (check_col(pinfo->cinfo, COL_INFO))
3331 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3332 response_expected ? "two-way" : "one-way");
3336 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3337 "Response expected: %u", response_expected);
3340 if( header->GIOP_version.minor > 0)
3342 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3345 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3346 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3353 /* Length of object_key sequence */
3354 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3359 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3360 /**/ "Object Key length: %u", objkey_len);
3365 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3367 print_objkey = make_printable_string(objkey, objkey_len);
3371 proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
3372 /**/ "Object Key: %s", print_objkey);
3376 g_free( print_objkey );
3380 * Register a cleanup function in case on of our tvbuff accesses
3381 * throws an exception. We need to clean up objkey.
3383 CLEANUP_PUSH(g_free, objkey);
3385 /* length of operation string and string */
3386 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3389 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3390 /**/ "Operation length: %u", len);
3395 if (check_col(pinfo->cinfo, COL_INFO))
3397 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3401 proto_tree_add_text (request_tree, tvb, offset - len, len,
3402 /**/ "Operation: %s", operation);
3408 * Register a cleanup function in case on of our tvbuff accesses
3409 * throws an exception. We need to clean up operation.
3411 CLEANUP_PUSH(g_free, operation);
3413 /* length of requesting_principal string */
3414 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3417 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3418 /**/ "Requesting Principal Length: %u", len);
3423 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3425 print_requesting_principal = make_printable_string(requesting_principal, len);
3429 proto_tree_add_text (request_tree, tvb, offset - len, len,
3430 /**/ "Requesting Principal: %s", print_requesting_principal);
3434 g_free( print_requesting_principal );
3435 g_free( requesting_principal );
3440 * Save FN,reqid,and operation for later. Add sub_handle later.
3441 * But only if user is NOT clicking.
3444 if (! pinfo->fd->flags.visited)
3445 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3446 request_id,operation,NULL);
3450 * Call subdissector here before freeing "operation" and "key"
3451 * pass request_id also.
3452 * First try an find an explicit sub_dissector, then if that
3453 * fails, try the heuristic method.
3458 header->req_id = request_id; /* save for sub dissector */
3459 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3463 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3466 /* Only call heuristic if no explicit dissector was found */
3469 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3474 * We're done with operation, so we can call the cleanup handler to free
3475 * it, and then pop the cleanup handler.
3477 CLEANUP_CALL_AND_POP;
3480 * We're done with objkey, so we can call the cleanup handler to free
3481 * it, and then pop the cleanup handler.
3483 CLEANUP_CALL_AND_POP;
3487 /** The format of a GIOP 1.2 RequestHeader message is
3488 * (CORBA 2.4, sec. 15.4.2):
3490 * struct RequestHeader_1_2 {
3491 * unsigned long request_id;
3492 * octet response_flags;
3493 * octet reserved[3];
3494 * TargetAddress target;
3496 * IOP::ServiceContextList service_context;
3497 * // requesting_principal not in GIOP 1.2
3501 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3502 proto_tree * tree, proto_tree * clnp_tree,
3503 MessageHeader * header, gboolean stream_is_big_endian)
3508 guint8 response_flags;
3510 gchar *operation = NULL;
3511 proto_tree *request_tree = NULL;
3513 gboolean exres = FALSE; /* result of trying explicit dissectors */
3515 gchar *repoid = NULL;
3520 tf = proto_tree_add_text (tree, tvb, offset,
3522 "General Inter-ORB Protocol Request");
3523 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3526 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3527 if (check_col(pinfo->cinfo, COL_INFO))
3529 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3533 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3534 "Request id: %u", request_id);
3537 response_flags = tvb_get_guint8( tvb, offset );
3541 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3542 "Response flags: %s (%u)",
3543 match_strval(response_flags, sync_scope),
3547 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3550 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3551 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3555 dissect_target_address(tvb, pinfo, &offset, request_tree, header, stream_is_big_endian);
3557 /* length of operation string */
3558 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3561 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3562 /**/ "Operation length: %u", len);
3567 if (check_col(pinfo->cinfo, COL_INFO))
3569 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3573 proto_tree_add_text (request_tree, tvb, offset - len, len,
3574 /**/ "Operation: %s", operation);
3581 * Register a cleanup function in case on of our tvbuff accesses
3582 * throws an exception. We need to clean up operation.
3584 CLEANUP_PUSH(g_free, operation);
3587 * Decode IOP::ServiceContextList
3590 decode_ServiceContextList(tvb, pinfo, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3593 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3594 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3595 * GIOP octet stream start.
3598 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3601 * Save FN,reqid,and operation for later. Add sub_handle later.
3602 * But only if user is NOT clicking.
3605 if (! pinfo->fd->flags.visited)
3606 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3607 request_id,operation,NULL);
3611 * Call sub dissector.
3612 * First try an find a explicit sub_dissector, then if that
3613 * fails, try the heuristic method.
3618 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3621 /* Only call heuristic if no explicit dissector was found */
3624 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3629 * We're done with operation, so we can call the cleanup handler to free
3630 * it, and then pop the cleanup handler.
3632 CLEANUP_CALL_AND_POP;
3636 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3637 proto_tree * tree, MessageHeader * header,
3638 gboolean stream_is_big_endian)
3644 gchar *p_object_key;
3645 proto_tree *locate_request_tree = NULL;
3650 tf = proto_tree_add_text (tree, tvb, offset,
3652 "General Inter-ORB Locate Request");
3653 if (locate_request_tree == NULL)
3655 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3660 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3661 if (check_col(pinfo->cinfo, COL_INFO))
3663 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3665 if (locate_request_tree)
3667 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3668 "Request id: %u", request_id);
3671 if(header->GIOP_version.minor < 2)
3673 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3674 if (locate_request_tree)
3676 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3677 "Object Key length: %u", len);
3681 get_CDR_octet_seq(tvb, &object_key, &offset, len);
3683 p_object_key = make_printable_string(object_key, len);
3685 if(locate_request_tree)
3688 proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
3689 "Object Key: %s", p_object_key);
3692 g_free(p_object_key);
3696 else /* GIOP 1.2 and higher */
3698 dissect_target_address(tvb, pinfo, &offset, locate_request_tree, header,
3699 stream_is_big_endian);
3705 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3706 proto_tree * tree, MessageHeader * header,
3707 gboolean stream_is_big_endian)
3711 guint32 locate_status;
3714 proto_tree *locate_reply_tree = NULL;
3719 tf = proto_tree_add_text (tree, tvb, offset,
3721 "General Inter-ORB Locate Reply");
3722 if (locate_reply_tree == NULL)
3724 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3729 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3730 if (check_col(pinfo->cinfo, COL_INFO))
3732 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3734 if (locate_reply_tree)
3736 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3737 "Request id: %u", request_id);
3740 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3741 if (locate_reply_tree)
3743 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3744 "Locate status: %s",
3745 match_strval(locate_status, giop_locate_status_types)
3749 /* Decode the LocateReply body.
3751 * For GIOP 1.0 and 1.1 body immediately follows header.
3752 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3756 if (header->GIOP_version.minor > 1) {
3757 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3761 switch(locate_status) {
3762 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3763 case OBJECT_FORWARD_PERM:
3764 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3766 case LOC_SYSTEM_EXCEPTION:
3767 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3769 case LOC_NEEDS_ADDRESSING_MODE:
3770 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3771 if(locate_reply_tree) {
3772 proto_tree_add_text (tree, tvb, offset -2, 2,
3773 "AddressingDisposition: %u", addr_disp);
3776 default: /* others have no reply body */
3783 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3784 MessageHeader * header, gboolean stream_is_big_endian)
3788 proto_tree *fragment_tree = NULL;
3793 tf = proto_tree_add_text (tree, tvb, offset,
3795 "General Inter-ORB Fragment");
3796 if (fragment_tree == NULL)
3798 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3803 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3804 if (check_col(pinfo->cinfo, COL_INFO))
3806 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3810 proto_tree_add_text (fragment_tree, tvb, offset-4, 4,
3811 "Request id: %u", request_id);
3817 /* Main entry point */
3819 gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3821 MessageHeader header;
3822 tvbuff_t *giop_header_tvb;
3823 tvbuff_t *payload_tvb;
3825 proto_tree *clnp_tree = NULL;
3828 u_int minor_version;
3829 gboolean stream_is_big_endian;
3835 giop_dump_collection(cd_module_hash);
3836 giop_dump_collection(cd_objkey_hash);
3837 giop_dump_collection(cd_heuristic_users);
3838 giop_dump_collection(cd_complete_reply_hash);
3839 giop_dump_collection(cd_complete_request_list);
3842 header.exception_id = NULL;
3844 /* check magic number and version */
3847 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
3849 if (tvb_length_remaining(tvb, 0) < GIOP_HEADER_SIZE)
3851 /* Not enough data captured to hold the GIOP header; don't try
3852 to interpret it as GIOP. */
3856 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3857 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3860 * because I have added extra elements in MessageHeader struct
3861 * for sub dissectors. -- FS
3864 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3866 if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
3868 /* Not a GIOP message. */
3873 if (check_col (pinfo->cinfo, COL_PROTOCOL))
3875 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3878 if (header.GIOP_version.major != GIOP_MAJOR ||
3879 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3881 /* Bad version number; should we note that and dissect the rest
3882 as data, or should we return FALSE on the theory that it
3883 might have been some other packet that happened to begin with
3884 "GIOP"? We shouldn't do *both*, so we return TRUE, for now.
3885 If we should return FALSE, we should do so *without* setting
3886 the "Info" column, *without* setting the "Protocol" column,
3887 and *without* adding anything to the protocol tree. */
3889 if (check_col (pinfo->cinfo, COL_INFO))
3891 col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3892 header.GIOP_version.major, header.GIOP_version.minor);
3896 ti = proto_tree_add_item (tree, proto_giop, tvb, 0,
3897 tvb_length (tvb), FALSE);
3898 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3899 proto_tree_add_text (clnp_tree, giop_header_tvb, 0,
3900 tvb_length (giop_header_tvb),
3901 "Version %u.%u not supported",
3902 header.GIOP_version.major,
3903 header.GIOP_version.minor);
3905 call_dissector(data_handle,payload_tvb, pinfo, tree);
3909 if (check_col (pinfo->cinfo, COL_INFO))
3911 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3912 header.GIOP_version.major, header.GIOP_version.minor,
3913 val_to_str(header.message_type, giop_message_types,
3914 "Unknown message type (0x%02x)"));
3917 stream_is_big_endian = is_big_endian (&header);
3919 if (stream_is_big_endian)
3920 message_size = pntohl (&header.message_size);
3922 message_size = pletohl (&header.message_size);
3926 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, 12, FALSE);
3927 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3928 proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3929 "Magic number: %s", GIOP_MAGIC);
3930 proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3932 header.GIOP_version.major,
3933 header.GIOP_version.minor);
3934 switch (minor_version)
3938 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3939 "Flags: 0x%02x (%s %s)",
3941 (stream_is_big_endian) ? "big-endian" : "little-endian",
3942 (header.flags & 0x02) ? " fragment" : "");
3945 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3946 "Byte ordering: %s-endian",
3947 (stream_is_big_endian) ? "big" : "little");
3951 } /* minor_version */
3953 proto_tree_add_uint_format (clnp_tree,
3954 hf_giop_message_type,
3955 giop_header_tvb, 7, 1,
3956 header.message_type,
3957 "Message type: %s", match_strval(header.message_type, giop_message_types));
3959 proto_tree_add_uint (clnp_tree,
3960 hf_giop_message_size,
3961 giop_header_tvb, 8, 4, message_size);
3966 if (check_col (pinfo->cinfo, COL_INFO))
3968 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3969 header.GIOP_version.major, header.GIOP_version.minor,
3970 match_strval(header.message_type, giop_message_types));
3974 switch (header.message_type)
3978 if(header.GIOP_version.minor < 2)
3980 dissect_giop_request_1_1 (payload_tvb, pinfo, tree, clnp_tree,
3981 &header, stream_is_big_endian);
3985 dissect_giop_request_1_2 (payload_tvb, pinfo, tree, clnp_tree,
3986 &header, stream_is_big_endian);
3993 if(header.GIOP_version.minor < 2)
3995 dissect_giop_reply (payload_tvb, pinfo, tree, clnp_tree, &header,
3996 stream_is_big_endian);
4000 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree, clnp_tree,
4001 &header, stream_is_big_endian);
4005 dissect_giop_cancel_request(payload_tvb, pinfo, tree, clnp_tree,
4006 &header, stream_is_big_endian);
4009 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
4010 stream_is_big_endian);
4013 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
4014 stream_is_big_endian);
4017 dissect_giop_fragment(payload_tvb, pinfo, tree, &header,
4018 stream_is_big_endian);
4023 } /* switch message_type */
4027 * XXX - we should catch exceptions here, so that we can free
4028 * this if an exception is thrown.
4029 * We'd then have to forward the exception.
4031 if (header.exception_id != NULL)
4032 g_free(header.exception_id);
4038 proto_register_giop (void)
4040 static hf_register_info hf[] = {
4041 { &hf_giop_message_type,
4042 { "Message type", "giop.type",
4043 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4046 { &hf_giop_message_size,
4047 { "Message size", "giop.len",
4048 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4052 { "Repository ID", "giop.repoid",
4053 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4056 { &hf_giop_string_length,
4057 { "String Length", "giop.strlen",
4058 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4061 { &hf_giop_sequence_length,
4062 { "Sequence Length", "giop.seqlen",
4063 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4066 { &hf_giop_profile_id,
4067 { "Profile ID", "giop.profid",
4068 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
4073 { "IOR::type_id", "giop.typeid",
4074 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4077 { &hf_giop_iiop_v_maj,
4078 { "IIOP Major Version", "giop.iiop_vmaj",
4079 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4082 { &hf_giop_iiop_v_min,
4083 { "IIOP Minor Version", "giop.iiop_vmin",
4084 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4087 { &hf_giop_endianess,
4088 { "Endianess", "giop.endianess",
4089 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4092 { &hf_giop_IIOP_tag,
4093 { "IIOP Component TAG", "giop.iioptag",
4094 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4098 { "IOR Profile TAG", "giop.iortag",
4099 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4103 { "TypeCode enum", "giop.TCKind",
4104 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4107 { &hf_giop_typecode_count,
4108 { "TypeCode count", "giop.tccount",
4109 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4112 { &hf_giop_typecode_default_used,
4113 { "default_used", "giop.tcdefault_used",
4114 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4117 { &hf_giop_typecode_digits,
4118 { "Digits", "giop.tcdigits",
4119 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4123 { &hf_giop_typecode_length,
4124 { "Length", "giop.tclength",
4125 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4128 { &hf_giop_typecode_max_length,
4129 { "Maximum length", "giop.tcmaxlen",
4130 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4133 { &hf_giop_typecode_member_name,
4134 { "TypeCode member name", "giop.tcmemname",
4135 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4138 { &hf_giop_typecode_name,
4139 { "TypeCode name", "giop.tcname",
4140 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4143 { &hf_giop_typecode_scale,
4144 { "Scale", "giop.tcscale",
4145 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4148 { &hf_giop_typecode_ValueModifier,
4149 { "ValueModifier", "giop.tcValueModifier",
4150 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4153 { &hf_giop_typecode_Visibility,
4154 { "Visibility", "giop.tcVisibility",
4155 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4160 { &hf_giop_type_boolean,
4161 { "TypeCode boolean data", "giop.tcboolean",
4162 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4165 { &hf_giop_type_char,
4166 { "TypeCode char data", "giop.tcchar",
4167 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4170 { &hf_giop_type_double,
4171 { "TypeCode double data", "giop.tcdouble",
4172 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4175 { &hf_giop_type_enum,
4176 { "TypeCode enum data", "giop.tcenumdata",
4177 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4181 * float as double ?? -- FIX
4184 { &hf_giop_type_float,
4185 { "TypeCode float data", "giop.tcfloat",
4186 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4189 { &hf_giop_type_long,
4190 { "TypeCode long data", "giop.tclongdata",
4191 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4194 { &hf_giop_type_octet,
4195 { "TypeCode octet data", "giop.tcoctet",
4196 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4199 { &hf_giop_type_short,
4200 { "TypeCode short data", "giop.tcshortdata",
4201 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4204 { &hf_giop_type_string,
4205 { "TypeCode string data", "giop.tcstring",
4206 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4209 { &hf_giop_type_ulong,
4210 { "TypeCode ulong data", "giop.tculongdata",
4211 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4214 { &hf_giop_type_ushort,
4215 { "TypeCode ushort data", "giop.tcushortdata",
4216 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4220 * IIOP Module - Chapter 15.10.2
4223 { &hf_giop_iiop_host,
4224 { "IIOP::Profile_host", "giop.iiop.host",
4225 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4229 { &hf_giop_iiop_port,
4230 { "IIOP::Profile_port", "giop.iiop.port",
4231 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4236 * IIOP ServiceContext
4239 { &hf_giop_iop_vscid,
4240 { "VSCID", "giop.iiop.vscid",
4241 FT_UINT32, BASE_HEX, NULL, 0xfffff000, "", HFILL }
4245 { &hf_giop_iop_scid,
4246 { "SCID", "giop.iiop.scid",
4247 FT_UINT32, BASE_HEX, NULL, 0x00000fff, "", HFILL }
4254 static gint *ett[] = {
4258 &ett_giop_cancel_request,
4259 &ett_giop_locate_request,
4260 &ett_giop_locate_reply,
4266 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4268 proto_register_field_array (proto_giop, hf, array_length (hf));
4269 proto_register_subtree_array (ett, array_length (ett));
4272 /* register init routine */
4274 register_init_routine( &giop_init); /* any init stuff */
4277 * Init the giop user module hash tables here, as giop users
4278 * will populate it via register_giop_user_module BEFORE my
4279 * own giop_init() is called.
4282 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4284 giop_module_keys = g_mem_chunk_new("giop_module_keys",
4285 sizeof(struct giop_module_key),
4286 giop_module_init_count * sizeof(struct giop_module_key),
4289 giop_module_vals = g_mem_chunk_new("giop_module_vals",
4290 sizeof(struct giop_module_val),
4291 giop_module_init_count * sizeof(struct giop_module_val),
4298 void proto_reg_handoff_giop (void) {
4299 data_handle = find_dissector("data");
4300 heur_dissector_add("tcp", dissect_giop, proto_giop);
4309 * Ref Corba v2.4.2 Chapter 13
4317 typedef unsigned long ProfileId;
4319 const ProfileId TAG_INTERNET_IOP = 0;
4320 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4322 struct TaggedProfile {
4324 sequence <octet> profile_data;
4329 sequence <TaggedProfile> profiles;
4332 typedef unsigned long ComponentId;
4334 struct TaggedComponent {
4336 sequence <octet> component_data;
4339 typedef sequence <TaggedComponent> MultipleComponentProfile;
4345 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4346 guint32 boundary, gboolean stream_is_big_endian) {
4349 guint32 seqlen_p; /* sequence length of profiles */
4352 proto_tree *tree = NULL; /* IOR tree */
4355 gchar *repobuf; /* for repository ID */
4359 /* create a subtree */
4362 tf = proto_tree_add_text (ptree, tvb, *offset, tvb_length (tvb), "IOR");
4363 tree = proto_item_add_subtree (tf, ett_giop_ior);
4367 /* Get type_id == Repository ID */
4369 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4372 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4373 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4375 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4376 *offset-u_octet4,u_octet4,repobuf);
4381 * Register a cleanup function in case on of our tvbuff accesses
4382 * throws an exception. We need to clean up repobuf.
4383 * We can't free it yet, as we must wait until we have the object
4384 * key, as we have to add both to the hash table.
4386 CLEANUP_PUSH(g_free, repobuf);
4388 /* Now get a sequence of profiles */
4389 /* Get sequence length (number of elements) */
4391 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4393 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4394 *offset-sizeof(seqlen_p),4,seqlen_p);
4398 /* fetch all TaggedProfiles in this sequence */
4400 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4401 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4405 * We're done with repobuf, so we can call the cleanup handler to free
4406 * it, and then pop the cleanup handler.
4408 CLEANUP_CALL_AND_POP;
4412 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4413 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4415 guint32 seqlen_pd; /* sequence length of profile data */
4417 guint32 pidtag; /* profile ID TAG */
4419 gchar *profile_data; /* profile_data pointer */
4420 gchar *p_profile_data; /* printable profile_data pointer */
4422 guint32 new_boundary; /* for encapsulations encountered */
4423 gboolean new_big_endianess; /* for encapsulations encountered */
4425 /* Get ProfileId tag */
4427 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4430 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4431 *offset-sizeof(pidtag),4,pidtag);
4434 /* get sequence length, new endianness and boundary for encapsulation */
4436 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4437 stream_is_big_endian, boundary,
4438 &new_big_endianess, &new_boundary);
4440 /* return if zero length sequence */
4447 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4448 * decode it, otherwise just dump the octet sequence
4450 * also, store IOR in our objectkey hash
4452 * TODO - handle other TAGS
4456 case IOP_TAG_INTERNET_IOP:
4458 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4463 /* fetch all octets in this sequence , but skip endianess */
4465 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4467 /* Make a printable string */
4469 p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4472 proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4473 "Profile Data: %s", p_profile_data);
4476 g_free(p_profile_data);
4478 g_free(profile_data);
4489 * Decode IIOP IOR Profile
4490 * Ref Chap 15.7.2 in Corba Spec
4494 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4495 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4496 gboolean store_flag) {
4498 guint32 i; /* loop index */
4500 guint8 v_major,v_minor; /* IIOP sersion */
4502 guint32 u_octet4; /* u long */
4503 guint16 u_octet2; /* u short */
4504 guint32 seqlen; /* generic sequence length */
4505 guint32 seqlen1; /* generic sequence length */
4506 gchar *objkey; /* object key pointer */
4507 gchar *p_chars; /* printable characters pointer */
4510 /* Get major/minor version */
4512 v_major = get_CDR_octet(tvb,offset);
4513 v_minor = get_CDR_octet(tvb,offset);
4517 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4518 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4519 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4520 *offset-sizeof(v_minor),1,v_minor );
4526 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4529 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4530 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4532 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4533 *offset-u_octet4,u_octet4,buf);
4537 g_free(buf); /* dont forget */
4541 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4544 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4545 *offset-sizeof(u_octet2),2,u_octet2);
4549 /* Object Key - sequence<octet> object_key */
4551 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4554 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4555 *offset-sizeof(seqlen),4,seqlen);
4559 /* fetch all octets in this sequence */
4560 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4563 * Now we may have the Repository ID from earlier, as well
4564 * as the object key sequence and lengh. So lets store them in
4565 * our objectkey hash and free buffers.
4567 * But only insert if user is not clicking and repo id not NULL.
4573 if(!pinfo->fd->flags.visited)
4574 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4579 * No pinfo, but store anyway if flag set. eg: IOR read from file
4583 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4587 /* Make a printable string */
4589 p_chars = make_printable_string( objkey, seqlen );
4592 proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
4593 "Object Key: %s", p_chars);
4601 * Now see if if its v1.1 or 1.2, as they can contain
4602 * extra sequence of IOP::TaggedComponents
4615 /* sequence of IOP::TaggedComponents */
4616 /* Ref Chap 13 in Corba Spec */
4618 /* get sequence length */
4619 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4622 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4623 *offset-sizeof(seqlen),4,seqlen);
4626 for (i=0; i< seqlen; i++) {
4628 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4630 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4631 *offset-sizeof(u_octet4),4,u_octet4);
4634 /* get component_data */
4635 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4637 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4638 *offset-sizeof(seqlen1),4,seqlen1);
4642 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4645 /* Make a printable string of data */
4647 p_chars = make_printable_string(buf, seqlen1);
4649 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4650 "component_data: %s", p_chars);
4664 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4672 * Service Contexts Begin
4680 void dissect_SID_BI_DIR_IIOP(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4681 MessageHeader *header, gchar *operation, guint32 boundary) {
4691 * Service Contexts End
4703 * typedef unsigned long ServiceID;
4705 * struct ServiceContext {
4706 * ServiceID context_id;
4707 * sequence <octet> context_data;
4709 * typedef sequence <ServiceContext> ServiceContextList;
4712 * Note: Spec says context_data is an encapsulation.
4719 void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4720 gboolean stream_is_be, guint32 boundary) {
4722 guint32 seqlen; /* sequence length */
4723 guint32 seqlen_cd; /* sequence length, context_data */
4725 proto_tree *tree = NULL; /* ServiceContext tree */
4729 gchar *context_data;
4730 gchar *p_context_data;
4733 guint32 vscid; /* Vendor Service context id */
4736 /* create a subtree */
4739 tf = proto_tree_add_text (ptree, tvb, *offset, tvb_length (tvb), "ServiceContextList");
4740 tree = proto_item_add_subtree (tf, ett_giop_scl);
4743 /* Get sequence length (number of elements) */
4745 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4747 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4748 *offset-sizeof(seqlen),4,seqlen);
4751 /* return if zero length sequence */
4756 /* Loop for all ServiceContext's */
4758 for (i=0; i<seqlen; i++) {
4760 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4762 proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4763 *offset-sizeof(context_id),4,context_id);
4765 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4766 *offset-sizeof(context_id),4,context_id);
4770 vscid = context_id && 0xfffff000; /* vendor info, top 20 bits */
4771 scid = context_id && 0x00000fff; /* standard service info, lower 12 bits */
4774 #if CONTEXT_DATA_IS_ENCAPSULATED
4776 /* get sequence length, new endianness and boundary for encapsulation */
4778 seqlen_cd = get_CDR_encap_info(tvb, tree, offset,
4779 stream_is_be, boundary,
4780 &new_big_endianess, &new_boundary);
4784 /* get sequence length, and NO encapsulation */
4786 seqlen_cd = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4790 /* return if zero length sequence */
4796 * Now decode sequence according to vendor ServiceId, but I dont
4797 * have that yet, so just dump it as data.
4800 /* fetch all octets in this sequence */
4802 get_CDR_octet_seq(tvb, &context_data, offset, seqlen_cd);
4804 /* Make a printable string */
4806 p_context_data = make_printable_string( context_data, seqlen_cd );
4809 proto_tree_add_text (tree, tvb, *offset - seqlen_cd , seqlen_cd,
4810 "context_data: %s", p_context_data);
4813 g_free(context_data);
4814 g_free(p_context_data);
4819 return; /* for now, fix later */
4824 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
4827 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
4828 gboolean stream_is_big_endian,
4831 guint32 length; /* string length */
4832 guint32 minor_code_value;
4833 guint32 completion_status;
4835 gchar *buf; /* pointer to string buffer */
4837 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
4840 proto_tree_add_text(tree, tvb, *offset-4, 4,
4841 "Exception length: %u", length);
4843 proto_tree_add_text(tree, tvb, *offset - length, length,
4844 "Exception id: %s", buf );
4849 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4850 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4853 proto_tree_add_text(tree, tvb, *offset-8, 4,
4854 "Minor code value: %u", minor_code_value);
4855 proto_tree_add_text(tree, tvb, *offset-4, 4,
4856 "Completion Status: %u", completion_status);
4862 * Helper functions for dissecting TypeCodes
4864 * These functions decode the complex parameter lists
4865 * of TypeCodes as defined in the CORBA spec chapter 15.
4868 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4869 gboolean stream_is_big_endian, guint32 boundary,
4870 MessageHeader * header) {
4872 guint32 new_boundary; /* new boundary for encapsulation */
4873 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4875 guint32 seqlen; /* sequence length */
4877 /* get sequence length, new endianness and boundary for encapsulation */
4878 seqlen = get_CDR_encap_info(tvb, tree, offset,
4879 stream_is_big_endian, boundary,
4880 &new_stream_is_big_endian, &new_boundary);
4882 /* get repository ID */
4883 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4887 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4888 hf_giop_typecode_name);
4893 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4894 gboolean stream_is_big_endian, guint32 boundary,
4895 MessageHeader * header ) {
4897 guint32 new_boundary; /* new boundary for encapsulation */
4898 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4900 guint32 count; /* parameter count (of tuples) */
4901 guint32 seqlen; /* sequence length */
4902 guint32 i; /* loop index */
4904 /* get sequence lengt,h new endianness and boundary for encapsulation */
4905 seqlen = get_CDR_encap_info(tvb, tree, offset,
4906 stream_is_big_endian, boundary,
4907 &new_stream_is_big_endian, &new_boundary);
4909 /* get repository ID */
4910 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4914 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4915 hf_giop_typecode_name);
4917 /* get count of tuples */
4918 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4920 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4921 *offset-sizeof(count),4,count);
4924 /* get all tuples */
4925 for (i=0; i< count; i++) {
4926 /* get member name */
4927 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4928 hf_giop_typecode_member_name);
4930 /* get member type */
4931 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4937 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4938 gboolean stream_is_big_endian, guint32 boundary,
4939 MessageHeader * header) {
4941 guint32 new_boundary; /* new boundary for encapsulation */
4942 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4944 guint32 TCKind; /* TypeCode */
4945 gint32 s_octet4; /* signed int32 */
4947 guint32 count; /* parameter count (of tuples) */
4948 guint32 seqlen; /* sequence length */
4949 guint32 i; /* loop index */
4951 /* get sequence legnth, new endianness and boundary for encapsulation */
4952 seqlen = get_CDR_encap_info(tvb, tree, offset,
4953 stream_is_big_endian, boundary,
4954 &new_stream_is_big_endian, &new_boundary);
4956 /* get repository ID */
4957 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4961 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4962 hf_giop_typecode_name);
4964 /* get discriminant type */
4965 TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4967 /* get default used */
4968 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
4970 proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
4971 *offset-sizeof(s_octet4),4,s_octet4);
4973 /* get count of tuples */
4974 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4976 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4977 *offset-sizeof(count),4,count);
4980 /* get all tuples */
4981 for (i=0; i< count; i++) {
4982 /* get label value, based on TCKind above */
4983 dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
4985 /* get member name */
4986 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4987 hf_giop_typecode_member_name);
4989 /* get member type */
4990 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4996 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4997 gboolean stream_is_big_endian, guint32 boundary,
4998 MessageHeader * header) {
5000 guint32 new_boundary; /* new boundary for encapsulation */
5001 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5003 guint32 count; /* parameter count (of tuples) */
5004 guint32 seqlen; /* sequence length */
5005 guint32 i; /* loop index */
5007 /* get sequence length, new endianness and boundary for encapsulation */
5008 seqlen = get_CDR_encap_info(tvb, tree, offset,
5009 stream_is_big_endian, boundary,
5010 &new_stream_is_big_endian, &new_boundary);
5012 /* get repository ID */
5013 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5017 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5018 hf_giop_typecode_name);
5020 /* get count of tuples */
5021 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5023 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5024 *offset-sizeof(count),4,count);
5027 /* get all tuples */
5028 for (i=0; i< count; i++) {
5029 /* get member name */
5030 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5031 hf_giop_typecode_member_name);
5037 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5038 gboolean stream_is_big_endian, guint32 boundary,
5039 MessageHeader * header) {
5041 guint32 new_boundary; /* new boundary for encapsulation */
5042 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5044 guint32 u_octet4; /* unsigned int32 */
5046 guint32 seqlen; /* sequence length */
5048 /* get sequence length, new endianness and boundary for encapsulation */
5049 seqlen = get_CDR_encap_info(tvb, tree, offset,
5050 stream_is_big_endian, boundary,
5051 &new_stream_is_big_endian, &new_boundary);
5053 /* get element type */
5054 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5056 /* get max length */
5057 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5059 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
5060 *offset-sizeof(u_octet4),4,u_octet4);
5065 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5066 gboolean stream_is_big_endian, guint32 boundary,
5067 MessageHeader * header) {
5069 guint32 new_boundary; /* new boundary for encapsulation */
5070 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5072 guint32 u_octet4; /* unsigned int32 */
5074 guint32 seqlen; /* sequence length */
5076 /* get sequence length, new endianness and boundary for encapsulation */
5077 seqlen = get_CDR_encap_info(tvb, tree, offset,
5078 stream_is_big_endian, boundary,
5079 &new_stream_is_big_endian, &new_boundary);
5081 /* get element type */
5082 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5085 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5087 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5088 *offset-sizeof(u_octet4),4,u_octet4);
5093 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5094 gboolean stream_is_big_endian, guint32 boundary,
5095 MessageHeader * header) {
5097 guint32 new_boundary; /* new boundary for encapsulation */
5098 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5100 guint32 seqlen; /* sequence length */
5102 /* get sequence legnth, new endianness and boundary for encapsulation */
5103 seqlen = get_CDR_encap_info(tvb, tree, offset,
5104 stream_is_big_endian, boundary,
5105 &new_stream_is_big_endian, &new_boundary);
5107 /* get repository ID */
5108 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5112 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5113 hf_giop_typecode_name);
5115 /* get ??? (noname) TypeCode */
5116 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5121 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5122 gboolean stream_is_big_endian, guint32 boundary,
5123 MessageHeader * header) {
5125 guint32 new_boundary; /* new boundary for encapsulation */
5126 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5128 guint32 count; /* parameter count (of tuples) */
5129 guint32 seqlen; /* sequence length */
5130 guint32 i; /* loop index */
5132 /* get sequence length, new endianness and boundary for encapsulation */
5133 seqlen = get_CDR_encap_info(tvb, tree, offset,
5134 stream_is_big_endian, boundary,
5135 &new_stream_is_big_endian, &new_boundary);
5137 /* get repository ID */
5138 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5142 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5143 hf_giop_typecode_name);
5145 /* get count of tuples */
5146 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5148 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5149 *offset-sizeof(count),4,count);
5152 /* get all tuples */
5153 for (i=0; i< count; i++) {
5154 /* get member name */
5155 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5156 hf_giop_typecode_member_name);
5158 /* get member type */
5159 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5165 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5166 gboolean stream_is_big_endian, guint32 boundary,
5167 MessageHeader * header) {
5169 guint32 new_boundary; /* new boundary for encapsulation */
5170 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5172 gint16 s_octet2; /* signed int16 */
5174 guint32 count; /* parameter count (of tuples) */
5175 guint32 seqlen; /* sequence length */
5176 guint32 i; /* loop index */
5178 /* get sequence length, new endianness and boundary for encapsulation */
5179 seqlen = get_CDR_encap_info(tvb, tree, offset,
5180 stream_is_big_endian, boundary,
5181 &new_stream_is_big_endian, &new_boundary);
5183 /* get repository ID */
5184 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5188 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5189 hf_giop_typecode_name);
5191 /* get ValueModifier */
5192 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5194 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5195 *offset-sizeof(s_octet2),2,s_octet2);
5198 /* get conrete base */
5199 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5201 /* get count of tuples */
5202 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5204 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5205 *offset-sizeof(count),4,count);
5208 /* get all tuples */
5209 for (i=0; i< count; i++) {
5210 /* get member name */
5211 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5212 hf_giop_typecode_member_name);
5214 /* get member type */
5215 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5217 /* get Visibility */
5218 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5220 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5221 *offset-sizeof(s_octet2),2,s_octet2);
5228 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5229 gboolean stream_is_big_endian, guint32 boundary,
5230 MessageHeader * header) {
5232 guint32 new_boundary; /* new boundary for encapsulation */
5233 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5235 guint32 seqlen; /* sequence length */
5237 /* get sequence length, new endianness and boundary for encapsulation */
5238 seqlen = get_CDR_encap_info(tvb, tree, offset,
5239 stream_is_big_endian, boundary,
5240 &new_stream_is_big_endian, &new_boundary);
5242 /* get repository ID */
5243 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5247 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5248 hf_giop_typecode_name);
5250 /* get ??? (noname) TypeCode */
5251 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5255 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5256 gboolean stream_is_big_endian, guint32 boundary,
5257 MessageHeader * header) {
5259 guint32 new_boundary; /* new boundary for encapsulation */
5260 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5262 guint32 seqlen; /* sequence length */
5264 /* get sequence length, new endianness and boundary for encapsulation */
5265 seqlen = get_CDR_encap_info(tvb, tree, offset,
5266 stream_is_big_endian, boundary,
5267 &new_stream_is_big_endian, &new_boundary);
5269 /* get repository ID */
5270 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5274 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5275 hf_giop_typecode_name);
5280 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5281 gboolean stream_is_big_endian, guint32 boundary,
5282 MessageHeader * header) {
5284 guint32 new_boundary; /* new boundary for encapsulation */
5285 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5287 guint32 seqlen; /* sequence length */
5289 /* get sequence length, new endianness and boundary for encapsulation */
5290 seqlen = get_CDR_encap_info(tvb, tree, offset,
5291 stream_is_big_endian, boundary,
5292 &new_stream_is_big_endian, &new_boundary);
5294 /* get repository ID */
5295 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5299 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5300 hf_giop_typecode_name);
5304 /* Typecode parameter lists are encoded as encapsulations and
5305 * this function gets the encapsulation information; see
5306 * CORBA spec chapter 15
5309 * Renamed to get_CDR_encap_info() for any encapsulation
5310 * we come across, useful helper function
5312 * Also, should return immediately if seqlen == 0.
5313 * ie: Forget about trying to grab endianess for
5314 * zero length sequence.
5316 * Caller must always check seqlen == 0, and not assume its value
5319 * Note: there seemed to be considerable confusion in corba
5320 * circles as to the correct interpretation of encapsulations,
5321 * and zero length sequences etc, but this is our best bet at the
5328 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5329 gboolean old_stream_is_big_endian, guint32 old_boundary,
5330 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5332 guint32 seqlen; /* sequence length */
5333 guint8 giop_endianess;
5335 /* Get sequence length of parameter list */
5336 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5338 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5339 *offset-sizeof(seqlen),4,seqlen);
5345 * seqlen == 0, implies no endianess and no data
5346 * so just return. Populate new_boundary_ptr and
5347 * new_stream_is_big_endian_ptr with current (old)
5348 * values, just to keep everyone happy. -- FS
5354 *new_boundary_ptr = old_boundary;
5355 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5361 /* Start of encapsulation of parameter list */
5362 *new_boundary_ptr = *offset; /* remember */
5363 giop_endianess = get_CDR_octet(tvb,offset);
5365 *new_stream_is_big_endian_ptr = ! giop_endianess;
5368 * Glib: typedef gint gboolean;
5369 * ie: It is not a guint8, so cannot use sizeof to correctly
5375 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5376 *offset-1,1,giop_endianess);
5386 * gets a TypeCode complex string parameter and
5387 * displays it in the relevant tree.
5390 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5391 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5393 guint32 u_octet4; /* unsigned int32 */
5394 gchar *buf; /* ptr to string buffer */
5397 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5400 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5401 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5403 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5407 g_free(buf); /* dont forget */
5412 * For a given data type, given by a TypeCode gets the associated data
5413 * and displays it in the relevant tree.
5416 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5417 gboolean stream_is_big_endian, guint32 boundary,
5418 MessageHeader * header, guint32 data_type ) {
5420 gboolean my_boolean; /* boolean */
5422 gint8 s_octet1; /* signed int8 */
5423 guint8 u_octet1; /* unsigned int8 */
5425 gint16 s_octet2; /* signed int16 */
5426 guint16 u_octet2; /* unsigned int16 */
5428 gint32 s_octet4; /* signed int32 */
5429 guint32 u_octet4; /* unsigned int32 */
5431 gdouble my_double; /* double */
5432 gfloat my_float; /* float */
5434 gchar *buf = NULL; /* ptr to string buffer */
5436 /* Grab the data according to data type */
5438 switch (data_type) {
5440 /* nothing to decode */
5443 /* nothing to decode */
5446 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5448 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5449 *offset-sizeof(s_octet2),2,s_octet2);
5453 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5455 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5456 *offset-sizeof(s_octet4),4,s_octet4);
5460 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5462 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5463 *offset-sizeof(u_octet2),2,u_octet2);
5467 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5469 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5470 *offset-sizeof(u_octet4),4,u_octet4);
5474 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5476 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5477 *offset-sizeof(my_float),4,my_float);
5481 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5483 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5484 *offset-sizeof(my_double),8,my_double);
5488 my_boolean = get_CDR_boolean(tvb,offset);
5490 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5491 *offset-1,1,my_boolean);
5495 u_octet1 = get_CDR_char(tvb,offset);
5497 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5498 *offset-sizeof(u_octet1),1,u_octet1);
5502 u_octet1 = get_CDR_octet(tvb,offset);
5504 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5505 *offset-sizeof(u_octet1),1,u_octet1);
5509 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5512 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5523 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5525 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5526 *offset-sizeof(u_octet4),4,u_octet4);
5530 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5532 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5533 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5535 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5536 *offset-u_octet4,u_octet4,buf);
5540 g_free(buf); /* dont forget */
5557 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5560 * XXX - can any of these throw an exception?
5561 * If so, we need to catch the exception and free "buf".
5563 if (s_octet1 < 0) { /* no size to add to tree */
5564 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5565 *offset+s_octet1,(-s_octet1),buf);
5567 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5568 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5569 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5570 *offset-s_octet1,s_octet1,buf);
5574 g_free(buf); /* dont forget */
5577 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5580 * XXX - can any of these throw an exception?
5581 * If so, we need to catch the exception and free "buf".
5583 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5584 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5585 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5586 *offset-u_octet4,u_octet4,buf);
5589 g_free(buf); /* dont forget */
5599 case tk_abstract_interface:
5602 g_warning("giop: Unknown typecode data type %u \n", data_type);