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.61 2002/05/13 01:24:45 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"
299 #include <epan/packet.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, 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);
347 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
348 gboolean stream_is_big_endian, guint32 boundary,
349 MessageHeader * header);
351 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
352 gboolean stream_is_big_endian, guint32 boundary,
353 MessageHeader * header );
355 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
356 gboolean stream_is_big_endian, guint32 boundary);
358 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
359 gboolean stream_is_big_endian, guint32 boundary,
360 MessageHeader * header);
362 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
363 gboolean stream_is_big_endian, guint32 boundary,
364 MessageHeader * header);
366 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
367 gboolean stream_is_big_endian, guint32 boundary,
368 MessageHeader * header);
370 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
371 gboolean stream_is_big_endian, guint32 boundary,
372 MessageHeader * header);
374 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
375 gboolean stream_is_big_endian, guint32 boundary,
376 MessageHeader * header);
378 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
379 gboolean stream_is_big_endian, guint32 boundary,
380 MessageHeader * header);
382 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
383 gboolean stream_is_big_endian, guint32 boundary);
385 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
386 gboolean stream_is_big_endian, guint32 boundary);
389 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
390 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
392 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
393 gboolean stream_is_big_endian, guint32 boundary,
394 MessageHeader * header, guint32 data_type );
400 * ------------------------------------------------------------------------------------------+
401 * Data/Variables/Structs
402 * ------------------------------------------------------------------------------------------+
406 static int proto_giop = -1;
407 static int hf_giop_message_type = -1;
408 static int hf_giop_message_size = -1;
409 static int hf_giop_repoid = -1;
410 static int hf_giop_string_length = -1;
411 static int hf_giop_sequence_length = -1;
412 static int hf_giop_profile_id = -1;
413 static int hf_giop_type_id = -1;
414 static int hf_giop_iiop_v_maj = -1;
415 static int hf_giop_iiop_v_min = -1;
416 static int hf_giop_endianess = -1; /* esp encapsulations */
417 static int hf_giop_IOR_tag = -1;
418 static int hf_giop_IIOP_tag = -1;
420 static int hf_giop_TCKind = -1;
421 static int hf_giop_typecode_count = -1;
422 static int hf_giop_typecode_default_used = -1;
423 static int hf_giop_typecode_digits = -1;
424 static int hf_giop_typecode_length = -1;
425 static int hf_giop_typecode_max_length = -1;
426 static int hf_giop_typecode_member_name = -1;
427 static int hf_giop_typecode_name = -1;
428 static int hf_giop_typecode_scale = -1;
429 static int hf_giop_typecode_ValueModifier = -1;
430 static int hf_giop_typecode_Visibility = -1;
432 static int hf_giop_type_boolean = -1;
433 static int hf_giop_type_char = -1;
434 static int hf_giop_type_double = -1;
435 static int hf_giop_type_enum = -1;
436 static int hf_giop_type_float = -1;
437 static int hf_giop_type_long = -1;
438 static int hf_giop_type_octet = -1;
439 static int hf_giop_type_short = -1;
440 static int hf_giop_type_string = -1;
441 static int hf_giop_type_ulong = -1;
442 static int hf_giop_type_ushort = -1;
444 static int hf_giop_iiop_host = -1;
445 static int hf_giop_iiop_port = -1;
446 static int hf_giop_iop_vscid = -1;
447 static int hf_giop_iop_scid = -1;
453 static gint ett_giop = -1;
454 static gint ett_giop_reply = -1;
455 static gint ett_giop_request = -1;
456 static gint ett_giop_cancel_request = -1;
457 static gint ett_giop_locate_request = -1;
458 static gint ett_giop_locate_reply = -1;
459 static gint ett_giop_fragment = -1;
461 static gint ett_giop_scl = -1; /* ServiceContextList */
462 static gint ett_giop_ior = -1; /* IOR */
464 static dissector_handle_t data_handle;
467 static const value_string giop_endianess_vals[] = {
468 { 0x0, "Big Endian" },
469 { 0x1, "Little Endian" },
473 static const value_string sync_scope[] = {
474 { 0x0, "SYNC_NONE" },
475 { 0x1, "SYNC_WITH_TRANSPORT"},
476 { 0x2, "SYNC_WITH_SERVER"},
477 { 0x3, "SYNC_WITH_TARGET"},
483 static const value_string profile_id_vals[] = {
484 { 0x0, "TAG_INTERNET_IOP" },
485 { 0x1, "TAG_MULTIPLE_COMPONENTS"},
486 { 0x2, "TAG_SCCP_IOP"},
490 static const value_string giop_message_types[] = {
493 { 0x2, "CancelRequest"},
494 { 0x3, "LocateRequest"},
495 { 0x4, "LocateReply"},
496 { 0x5, "CloseConnection"},
497 { 0x6, "MessageError"},
502 static const value_string giop_locate_status_types[] = {
503 { 0x0, "Unknown Object" },
504 { 0x1, "Object Here"},
505 { 0x2, "Object Forward"},
506 { 0x3, "Object Forward Perm"},
507 { 0x4, "Loc System Exception"},
508 { 0x5, "Loc Needs Addressing Mode"},
512 static const value_string tckind_vals[] = {
525 { 12, "tk_TypeCode"},
526 { 13, "tk_Principal"},
532 { 19, "tk_sequence"},
536 { 23, "tk_longlong"},
537 { 24, "tk_ulonglong"},
538 { 25, "tk_longdouble"},
543 { 30, "tk_value_box"},
545 { 32, "tk_abstract_interface"},
551 #define GIOP_MAGIC "GIOP"
554 * TAGS for IOR Profiles
556 * Chapter 13 Corba 2.4.2
560 #define IOP_TAG_INTERNET_IOP 0
561 #define IOP_TAG_MULTIPLE_COMPONENTS 1
564 /* Max Supported versions */
566 static const guint GIOP_MAJOR = 1;
567 static const guint GIOP_MINOR = 2;
570 static const int KeyAddr = 0;
571 static const int ProfileAddr = 1;
572 static const int ReferenceAddr = 2;
576 static const value_string reply_status_types[] = {
577 { NO_EXCEPTION, "No Exception" } ,
578 { USER_EXCEPTION, "User Exception" } ,
579 { SYSTEM_EXCEPTION, "System Exception" } ,
580 { LOCATION_FORWARD, "Location Forward" } ,
581 { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
582 { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
588 typedef enum LocateStatusType
593 OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
594 LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
595 LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
599 typedef struct LocateReplyHeader
602 guint32 locate_status;
608 * DATA - complete_request_list
611 static GList *giop_complete_request_list;
613 struct comp_req_list_entry {
614 guint32 fn; /* frame number */
615 gchar * operation; /* echo echoString */
616 giop_sub_handle_t *subh; /* handle to sub dissector */
617 guint32 reqid; /* request id */
618 gchar * repoid; /* repository ID */
621 typedef struct comp_req_list_entry comp_req_list_entry_t;
625 * DATA - complete_reply_hash
627 * Maps reply FN to request MFN
630 static int complete_reply_hash_count = 1000; /* storage size for our permanent data */
631 /* ie: 1000 entries -- needs tweaking -- FS */
633 struct complete_reply_hash_key {
634 guint32 fn; /* reply frame number */
637 struct complete_reply_hash_val {
638 guint32 mfn; /* matching frame number (request) */
641 GHashTable *giop_complete_reply_hash = NULL; /* hash */
642 GMemChunk *giop_complete_reply_keys = NULL; /* key storage */
643 GMemChunk *giop_complete_reply_vals = NULL; /* val storage */
647 * DATA - Module Hash stuff to store data from register_giop_user_module
649 * ie: module (or interface ?) name, and ptr to sub_dissector handle
651 * With this knowledge, we can call a sub dissector directly,
654 * objkey -> repoid -> sub_dissector via registered module/interface
659 static int giop_module_init_count = 100; /* storage size for our permanent data */
660 /* ie: 100 entries -- needs tweaking -- FS */
662 struct giop_module_key {
663 gchar *module; /* module (interface?) name */
666 struct giop_module_val {
667 giop_sub_handle_t *subh; /* handle to sub dissector */
670 GHashTable *giop_module_hash = NULL; /* hash */
671 GMemChunk *giop_module_keys = NULL; /* key storage */
672 GMemChunk *giop_module_vals = NULL; /* val storage */
676 * DATA - GSList to store list of function (dissector) pointers.
677 * for heuristic dissection.
681 static GSList *giop_sub_list = NULL;
684 * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
685 * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
687 * With this knowledge, we can call a sub dissector directly later
690 * objkey -> repoid -> sub_dissector via registered module/interface
692 * rather than heuristic calls that do not provide operation context.
693 * (unless we pass the RepoID for a given objkey -- hmmm)
698 * Interesting operation list, add more if you want to save
702 static const char giop_op_resolve[] = "resolve";
703 static const char giop_op_bind_new_context[] = "bind_new_context";
704 static const char giop_op_bind[] = "bind";
707 * Enums for interesting local operations, that we may need to monitor
708 * with their subsequent replies
713 request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
714 request_bind_new_context_op_val, /* bind_new_context */
715 request_bind_op_val, /* bind */
716 request_get_INIT_op_val, /* finding Nameserver */
722 * hash for mapping object keys onto object namespaces, so
723 * I can call the correct dissector.
729 * Where did I get the IOR from.
733 req_res = 0, /* REQUEST (resolve) */
734 file, /* stringified IOR' in a file */
738 typedef enum ior_src ior_src_t;
743 * Enums for my lists and hash's
746 enum collection_data {
747 cd_heuristic_users = 0,
750 cd_complete_request_list,
751 cd_complete_reply_hash
754 typedef enum collection_data collection_data_t;
758 static int giop_objkey_init_count = 100; /* storage size for our permanent data */
759 /* ie: 100 entries -- needs tweaking -- FS */
761 struct giop_object_key {
762 guint8 *objkey; /* ptr to object key */
763 guint32 objkey_len; /* length */
766 struct giop_object_val {
767 guint8 *repo_id; /* ptr to Repository ID string */
768 ior_src_t src; /* where did Iget this IOR from */
771 GHashTable *giop_objkey_hash = NULL; /* hash */
772 GMemChunk *giop_objkey_keys = NULL; /* key storage */
773 GMemChunk *giop_objkey_vals = NULL; /* val storage */
778 * ------------------------------------------------------------------------------------------+
779 * Private helper functions
780 * ------------------------------------------------------------------------------------------+
786 * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
789 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
790 GList * newlist_start;
791 comp_req_list_entry_t * entry = NULL;
794 entry = g_malloc(sizeof(comp_req_list_entry_t));
795 opn = g_strdup(op); /* duplicate operation for storage */
798 entry->reqid = reqid;
800 entry->operation = opn;
801 entry->repoid = NULL; /* dont have yet */
803 newlist_start = g_list_append (list, entry); /* append */
805 return newlist_start;
810 * Used to find an entry with matching Frame Number FN
811 * in the complete_request_list list.
814 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
816 GList * element; /* entry in list */
817 comp_req_list_entry_t * entry_ptr = NULL;
819 element = g_list_last(giop_complete_request_list); /* start from last */
821 while(element) { /* valid list entry */
822 entry_ptr = element->data; /* grab data pointer */
823 if (entry_ptr->fn == fn) { /* similar FN */
826 element = g_list_previous(element); /* try next previous */
829 return NULL; /* no match so return NULL */
834 * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
836 * Call this when you know a FN and matching giop_sub_handle_t and repoid
838 * This is done in say, try_explicit_dissector for example.
842 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
844 comp_req_list_entry_t * entry = NULL;
845 entry = find_fn_in_list(fn); /* grab FN data entry */
849 entry->repoid = g_strdup(repoid); /* copy and store */
857 /* giop_complete_reply_hash "EQUAL" Functions */
859 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
860 struct complete_reply_hash_key *mk1 = (struct complete_reply_hash_key *)v;
861 struct complete_reply_hash_key *mk2 = (struct complete_reply_hash_key *)w;
863 if (mk1->fn == mk2->fn) {
867 return 0; /* found differences */
870 /* giop_complete_reply_hash "HASH" Functions */
872 static guint32 complete_reply_hash_fn(gconstpointer v) {
873 guint32 val; /* init hash value */
874 struct complete_reply_hash_key *key = (struct complete_reply_hash_key *)v;
876 val = key->fn; /* simple and unique */
883 * Insert the FN and MFN together in our complete_reply_hash.
886 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
888 struct complete_reply_hash_key key, *new_key;
889 struct complete_reply_hash_val *val = NULL;
893 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
896 return; /* FN collision */
899 new_key = g_mem_chunk_alloc(giop_complete_reply_keys);
900 new_key->fn = fn; /* save FN */
902 val = g_mem_chunk_alloc(giop_complete_reply_vals);
903 val->mfn = mfn; /* and MFN */
905 g_hash_table_insert(giop_complete_reply_hash, new_key, val);
910 * Find the MFN values from a given FN key.
911 * Assumes the complete_reply_hash is already populated.
914 static guint32 get_mfn_from_fn(guint32 fn) {
916 struct complete_reply_hash_key key;
917 struct complete_reply_hash_val *val = NULL;
918 guint32 mfn = fn; /* save */
921 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
924 mfn = val->mfn; /* grab it */
927 return mfn; /* mfn or fn if not found */
932 * Attempt to find the MFN for this FN, and return it.
933 * Return MFN if found, or just FN if not. This is
934 * only used when we are building
937 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
939 GList * element; /* last entry in list */
940 comp_req_list_entry_t * entry_ptr = NULL;
942 /* Need Some pretty snappy code */
944 /* Loop back from current end of complete_request_list looking for */
945 /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
948 * As this routine is only called during initial pass of data,
949 * and NOT when a user clicks, it is ok to start from Current
950 * end of complete_request_list when searching for a match.
951 * As that list is bing populated in the same order as FN's
954 * Also, can make check for same reqid more detailed, but I start
955 * with reqid. Could add say port or address checks etc later ??
959 element = g_list_last(giop_complete_request_list); /* get last */
961 while(element) { /* valid list entry */
962 entry_ptr = element->data; /* grab data pointer */
963 if (entry_ptr->reqid == reqid) { /* similar reqid */
964 return entry_ptr->fn; /* return MFN */
966 element = g_list_previous(element); /* try next previous */
969 return fn; /* no match so return FN */
973 /* Module Hash "EQUAL" Functions */
975 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
976 struct giop_module_key *mk1 = (struct giop_module_key *)v;
977 struct giop_module_key *mk2 = (struct giop_module_key *)w;
979 if (!strcmp(mk1->module, mk2->module)) {
983 return 0; /* found differences */
986 /* Module Hash "HASH" Functions */
988 static guint32 giop_hash_module_hash(gconstpointer v) {
991 guint32 val = 0; /* init hash value */
993 struct giop_module_key *key = (struct giop_module_key *)v;
996 * Hmm, try this simple hashing scheme for now.
997 * ie: Simple summation, FIX later -- FS
1002 len = strlen(key->module);
1004 for (i=0; i<len; i++) {
1005 val += (guint8) key->module[i];
1014 * ------------------------------------------------------------------------------------------+
1015 * Public Utility functions
1016 * ------------------------------------------------------------------------------------------+
1023 * Routine to allow giop users to register their sub dissector function, name, and
1024 * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1025 * value returned from their proto_register_protocol(), so we can enable/disbale it
1026 * through the GUI (edit protocols).
1028 * This is used by try_explicit_giop_dissector() to find the
1029 * correct sub-dissector.
1033 void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
1035 struct giop_module_key module_key, *new_module_key;
1036 struct giop_module_val *module_val = NULL;
1038 module_key.module = module; /* module name */
1040 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1043 return; /* module name collision */
1046 /* So, passed module name should NOT exist in hash at this point.*/
1049 printf("giop:register_module: Adding Module %s to module hash \n", module);
1050 printf("giop:register_module: Module sub dissector name is %s \n", name);
1053 new_module_key = g_mem_chunk_alloc(giop_module_keys);
1054 new_module_key->module = module; /* save Module or interface name from IDL */
1056 module_val = g_mem_chunk_alloc(giop_module_vals);
1058 module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
1060 module_val->subh->sub_name = name; /* save dissector name */
1061 module_val->subh->sub_fn = sub; /* save subdissector*/
1062 module_val->subh->sub_proto = sub_proto; /* save subdissector's proto_XXX value */
1064 g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1071 /* Object Key Hash "EQUAL" Functions */
1073 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1074 struct giop_object_key *v1 = (struct giop_object_key *)v;
1075 struct giop_object_key *v2 = (struct giop_object_key *)w;
1077 if (v1->objkey_len != v2->objkey_len)
1078 return 0; /* no match because different length */
1080 /* Now do a byte comaprison */
1082 if (!memcmp(v1->objkey,v2->objkey, v1->objkey_len)) {
1083 return 1; /* compares ok */
1087 printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1090 return 0; /* found differences */
1093 /* Object Key Hash "HASH" Functions */
1095 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1096 struct giop_object_key *key = (struct giop_object_key *)v;
1099 guint32 val = 0; /* init hash value */
1103 * Hmm, try this simple hashing scheme for now.
1104 * ie: Simple summation
1110 printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1113 for (i=0; i< key->objkey_len; i++) {
1114 val += (guint8) key->objkey[i];
1122 * Routine to take an object key octet sequence, and length, and ptr to
1123 * a (null terminated )repository ID string, and store them in the obect key hash.
1125 * Blindly Inserts even if it does exist, See TODO at top for reason.
1128 static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
1130 struct giop_object_key objkey_key, *new_objkey_key;
1131 struct giop_object_val *objkey_val = NULL;
1133 objkey_key.objkey_len = len; /* length */
1134 objkey_key.objkey = obj; /* object key octet sequence */
1136 /* Look it up to see if it exists */
1138 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1140 /* CHANGED -- Same reqid, so abandon old entry */
1143 g_hash_table_remove(hash, &objkey_key);
1146 /* So, passed key should NOT exist in hash at this point.*/
1148 new_objkey_key = g_mem_chunk_alloc(giop_objkey_keys);
1149 new_objkey_key->objkey_len = len; /* save it */
1150 new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */
1152 objkey_val = g_mem_chunk_alloc(giop_objkey_vals);
1153 objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
1154 objkey_val->src = src; /* where IOR came from */
1158 printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
1159 objkey_val->repo_id, new_objkey_key->objkey_len);
1162 g_hash_table_insert(hash, new_objkey_key, objkey_val);
1169 * convert an ascii char representing a hex value,
1170 * to a numeric value.
1172 * returns value, or -1 if problem.
1176 static gint8 hex_char_to_val(guchar c){
1183 retval = c - 48; /* convert digit */
1187 c = toupper(c); /* convert to uppercase */
1188 if (c >= 'A' && c <= 'F') {
1199 * Convert from stringified IOR of the kind IOR:af4f7e459f....
1200 * to an IOR octet sequence.
1202 * User must free buffer.
1204 * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1205 * grab repoid etc for our objkey hash.
1209 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1212 gint8 tmpval; /* complete value */
1215 *out = g_new0(guint8, in_len); /* allocate buffer */
1221 /* skip past IOR: and convert character pairs to guint8 */
1223 for (i=4; i<in_len-1; i+=2) {
1224 if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1226 if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1227 g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1231 if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1232 g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1235 tmpval = tmpval_msb << 4;
1236 tmpval += tmpval_lsb;
1237 (*out)[(i-4)/2] = (guint8) tmpval;
1247 return (i-4)/2; /* length */
1254 * Simple getline, copied from somewhere :)
1258 static int getline(FILE *fp, gchar *line, int maxlen) {
1260 if (fgets(line,maxlen,fp) == NULL)
1263 return strlen(line);
1269 * Read a list of stringified IOR's from a named file, convert to IOR's
1270 * and store in object key hash
1273 static void read_IOR_strings_from_file(gchar *name, int max_iorlen) {
1274 guchar *buf; /* NOTE reused for every line */
1276 int ior_val_len; /* length after unstringifying. */
1278 guint8 *out; /* ptr to unstringified IOR */
1279 tvbuff_t *tvb; /* temp tvbuff for dissectin IORs */
1280 guint32 my_offset = 0;
1281 gboolean stream_is_big_endian;
1284 fp = fopen(name,"r"); /* open read only */
1287 if (errno == EACCES)
1288 fprintf(stderr, "Error opening file IOR.txt for reading: %s\n",strerror(errno));
1292 buf = g_malloc0(max_iorlen+1); /* input buf */
1294 while ((len = getline(fp,buf,max_iorlen+1)) > 0) {
1295 my_offset = 0; /* reset for every IOR read */
1297 ior_val_len = string_to_IOR(buf,len,&out); /* convert */
1301 /* Combination of tvb_new() and tvb_set_real_data().
1302 Can throw ReportedBoundsError.
1304 XXX - can it throw an exception in this case? If so, we
1305 need to catch it and clean up, but we really shouldn't allow
1306 it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
1309 tvb = tvb_new_real_data(out, ior_val_len, ior_val_len);
1311 stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1312 decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1322 fclose(fp); /* be nice */
1330 * Init routine, setup our request hash stuff, or delete old ref's
1332 * Cannot setup the module hash here as my init() may not be called before
1333 * users start registering. So I will move the module_hash stuff to
1334 * proto_register_giop, as is done with packet-rpc
1338 * Also, setup our objectkey/repoid hash here.
1342 static void giop_init(void) {
1346 * Create objkey/repoid hash, use my "equal" and "hash" functions.
1350 if (giop_objkey_hash)
1351 g_hash_table_destroy(giop_objkey_hash);
1352 if (giop_objkey_keys)
1353 g_mem_chunk_destroy(giop_objkey_keys);
1354 if (giop_objkey_vals)
1355 g_mem_chunk_destroy(giop_objkey_vals);
1359 * Create hash, use my "equal" and "hash" functions.
1363 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1365 giop_objkey_keys = g_mem_chunk_new("giop_objkey_keys",
1366 sizeof(struct giop_object_key),
1367 giop_objkey_init_count * sizeof(struct giop_object_key),
1370 giop_objkey_vals = g_mem_chunk_new("giop_objkey_vals",
1371 sizeof(struct giop_object_val),
1372 giop_objkey_init_count * sizeof(struct giop_object_val),
1377 * Create complete_reply_hash, use my "equal" and "hash" functions.
1381 if (giop_complete_reply_hash)
1382 g_hash_table_destroy(giop_complete_reply_hash);
1383 if (giop_complete_reply_keys)
1384 g_mem_chunk_destroy(giop_complete_reply_keys);
1385 if (giop_complete_reply_vals)
1386 g_mem_chunk_destroy(giop_complete_reply_vals);
1390 * Create hash, use my "equal" and "hash" functions.
1394 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1396 giop_complete_reply_keys = g_mem_chunk_new("giop_complete_reply_keys",
1397 sizeof(struct complete_reply_hash_key),
1398 complete_reply_hash_count * sizeof(struct complete_reply_hash_key),
1401 giop_complete_reply_vals = g_mem_chunk_new("giop_complete_reply_vals",
1402 sizeof(struct complete_reply_hash_val),
1403 complete_reply_hash_count * sizeof(struct complete_reply_hash_val),
1408 read_IOR_strings_from_file("IOR.txt", 600); /* testing */
1415 * Insert an entry in the GIOP Heuristic User table.
1417 * Uses giop_sub_handle_t to wrap giop user info.
1421 void register_giop_user(giop_sub_dissector_t *sub, gchar *name, int sub_proto) {
1423 giop_sub_handle_t *subh;
1425 subh = g_malloc(sizeof (giop_sub_handle_t));
1427 subh->sub_name = name;
1429 subh->sub_proto = sub_proto; /* proto_XXX from sub dissectors's proto_register_protocol() */
1431 giop_sub_list = g_slist_append (giop_sub_list, subh);
1437 * Lookup an object key in our object key hash, and return the corresponding
1442 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1444 struct giop_object_key objkey_key;
1445 struct giop_object_val *objkey_val = NULL;
1447 objkey_key.objkey_len = len; /* length */
1448 objkey_key.objkey = obj; /* object key octet sequence */
1450 /* Look it up to see if it exists */
1452 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1456 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1458 return objkey_val->repo_id; /* found */
1462 printf("FAILED Lookup of object key \n" );
1465 return NULL; /* not found */
1471 * Extract top level module/interface from repoid
1473 * eg from - "IDL:Echo/interface1:1.0"
1476 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1477 * get linux.org/Penguin/Teeth
1480 * User must free returned ptr after use.
1482 * TODO -- generalize for other Repoid encodings
1485 static gchar * get_modname_from_repoid(gchar *repoid) {
1487 gchar *modname = NULL;
1488 gchar *saved_repoid = NULL;
1490 guint8 stop_mod; /* Index of last character of modname in Repoid */
1491 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1494 saved_repoid = g_strdup(repoid); /* make a copy */
1496 /* Must start with IDL: , otherwise I get confused */
1498 if (g_strncasecmp("IDL:",repoid,4))
1501 /* Looks like a RepoID to me, so get Module or interface name */
1503 /* TODO -- put some code here to get Module name */
1505 for(i=4; c != '\0'; i++) {
1507 stop_mod = i; /* save */
1508 if (c == ':' ) /* delimiters */
1513 /* Now create a new string based on start and stop and \0 */
1515 modname = g_strndup(repoid+4, stop_mod - start_mod);
1530 * Display a "module" hash entry
1533 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1535 struct giop_module_val *mv = (struct giop_module_val *) val;
1536 struct giop_module_key *mk = (struct giop_module_key *) key;
1538 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1545 * Display a "complete_reply " hash entry
1548 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1550 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1551 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1553 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1561 * Display an "objkey" hash entry
1564 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1566 struct giop_object_val *mv = (struct giop_object_val *) val;
1567 struct giop_object_key *mk = (struct giop_object_key *) key;
1570 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1572 for (i=0; i<mk->objkey_len; i++) {
1573 printf("%.2x ", mk->objkey[i]);
1577 * If read from file, mark it as such..
1581 printf(", Repo ID = %s \n", mv->repo_id);
1584 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1592 * Display all giop_sub_list (GSList) entries
1595 static void display_heuristic_user_list() {
1598 giop_sub_handle_t *subh; /* handle */
1600 /* Get length of list */
1601 len = g_slist_length(giop_sub_list); /* find length */
1606 for (i=0; i<len; i++) {
1607 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1608 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1614 * Display all complete_request_list (GList) entries
1617 static void display_complete_request_list() {
1620 comp_req_list_entry_t *entry;
1622 /* Get length of list */
1623 len = g_list_length(giop_complete_request_list); /* find length */
1628 for (i=0; i<len; i++) {
1629 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1630 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1631 entry->reqid,entry->operation, entry->repoid);
1639 /* Dump Hash/List contents
1641 * collection_type specifies the list or hash to dump
1645 static void giop_dump_collection(collection_data_t collection_type) {
1647 switch(collection_type) {
1648 case cd_heuristic_users:
1649 printf("+----------------------------------------------+ \n");
1650 printf("+-------------- Heuristic User (Begin) --------+ \n");
1651 printf("+----------------------------------------------+ \n");
1653 display_heuristic_user_list();
1655 printf("+----------------------------------------------+ \n");
1656 printf("+-------------- Heuristic User (End) ----------+ \n");
1657 printf("+----------------------------------------------+ \n");
1661 case cd_complete_request_list:
1662 printf("+----------------------------------------------+ \n");
1663 printf("+------------- Complete Request List (Begin) --+ \n");
1664 printf("+----------------------------------------------+ \n");
1666 display_complete_request_list();
1668 printf("+----------------------------------------------+ \n");
1669 printf("+------------ Complete Request List (End) -----+ \n");
1670 printf("+----------------------------------------------+ \n");
1674 case cd_module_hash:
1675 printf("+----------------------------------------------+ \n");
1676 printf("+-------------- Module (Begin) ----------------+ \n");
1677 printf("+----------------------------------------------+ \n");
1679 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1681 printf("+----------------------------------------------+ \n");
1682 printf("+-------------- Module ( End) -----------------+ \n");
1683 printf("+----------------------------------------------+ \n\n");
1687 case cd_objkey_hash:
1688 printf("+----------------------------------------------+ \n");
1689 printf("+-------------- Objkey (Begin) ----------------+ \n");
1690 printf("+----------------------------------------------+ \n");
1692 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1694 printf("+----------------------------------------------+ \n");
1695 printf("+-------------- Objkey (End) ------------------+ \n");
1696 printf("+----------------------------------------------+ \n\n");
1700 case cd_complete_reply_hash:
1701 printf("+----------------------------------------------+ \n");
1702 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1703 printf("+----------------------------------------------+ \n");
1705 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1707 printf("+----------------------------------------------+ \n");
1708 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1709 printf("+----------------------------------------------+ \n");
1715 printf("giop: giop_dump_collection: Unknown type \n");
1726 * Loop through all subdissectors, and call them until someone
1727 * answers (returns TRUE). This function then returns TRUE, otherwise
1730 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1733 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1734 MessageHeader *header, gchar *operation ) {
1737 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1738 giop_sub_handle_t *subh = NULL;
1739 const char *saved_proto;
1741 len = g_slist_length(giop_sub_list); /* find length */
1746 saved_proto = pinfo->current_proto;
1747 for (i=0; i<len; i++) {
1748 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1750 if (proto_is_protocol_enabled(subh->sub_proto)) {
1751 pinfo->current_proto =
1752 proto_get_protocol_short_name(subh->sub_proto);
1753 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1755 pinfo->current_proto = saved_proto;
1756 return TRUE; /* found one, lets return */
1758 } /* protocol_is_enabled */
1761 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1762 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
1764 pinfo->current_proto = saved_proto;
1765 return res; /* result */
1771 * Find the matching repoid in the module hash and call
1772 * the dissector function if offset exists.
1775 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1776 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1782 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1783 MessageHeader *header, gchar *operation, gchar *repoid ) {
1785 giop_sub_handle_t *subdiss = NULL; /* handle */
1786 gboolean res = FALSE;
1787 gchar *modname = NULL;
1788 struct giop_module_key module_key;
1789 struct giop_module_val *module_val = NULL;
1790 const char *saved_proto;
1794 * Get top level module/interface from complete repoid
1797 modname = get_modname_from_repoid(repoid);
1798 if (modname == NULL) {
1799 return res; /* unknown module name */
1803 /* Search for Module or interface name */
1805 module_key.module = modname; /* module name */
1806 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1808 if (module_val == NULL) {
1809 return res; /* module not registered */
1812 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1815 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1816 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1817 /* but only if user not clicking */
1819 if (!pinfo->fd->flags.visited)
1820 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1823 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1825 if (tvb_offset_exists(tvb, *offset)) {
1827 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1830 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1832 saved_proto = pinfo->current_proto;
1833 pinfo->current_proto =
1834 proto_get_protocol_short_name(subdiss->sub_proto);
1835 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1836 pinfo->current_proto = saved_proto;
1838 } /* protocol_is_enabled */
1839 } /* offset exists */
1842 return res; /* return result */
1847 /* Take in an array of char and create a new string.
1848 * Replace non-printable characters with periods.
1850 * The array may contain \0's so dont use strdup
1851 * The string is \0 terminated, and thus longer than
1852 * the initial sequence.
1853 * Caller must free the new string.
1856 static gchar * make_printable_string (gchar *in, guint32 len) {
1858 gchar *print_string = NULL;
1860 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1861 memcpy(print_string, in, len); /* and make a copy of input data */
1863 for(i=0; i < len; i++) {
1864 if( !isprint( (unsigned char)print_string[i] ) )
1865 print_string[i] = '.';
1868 return print_string; /* return ptr */
1871 /* Determine the byte order from the GIOP MessageHeader */
1873 gboolean is_big_endian (MessageHeader * header) {
1874 gboolean big_endian = FALSE;
1876 switch (header->GIOP_version.minor) {
1879 if (header->flags & 0x01)
1899 * Calculate new offset, based on the current offset, and user supplied
1900 * "offset delta" value, and the alignment requirement.
1904 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1905 * aligned on 8 byte boundaries.
1908 static void set_new_alignment(int *offset, int delta, int alignment) {
1910 while( ( (*offset + delta) % alignment) != 0)
1919 * ------------------------------------------------------------------------------------------+
1920 * Public get_CDR_xxx functions.
1921 * ------------------------------------------------------------------------------------------+
1927 * Gets data of type any. This is encoded as a TypeCode
1928 * followed by the encoded value.
1931 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1932 gboolean stream_is_big_endian, int boundary,
1933 MessageHeader * header ) {
1935 guint32 TCKind; /* TypeCode */
1937 /* get TypeCode of any */
1938 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1940 /* dissect data of type TCKind */
1941 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1945 /* Copy a 1 octet sequence from the tvbuff
1946 * which represents a boolean value, and convert
1947 * it to a boolean value.
1948 * Offset is then incremented by 1, to indicate the 1 octet which
1949 * has been processed.
1952 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1955 val = tvb_get_guint8(tvb, *offset); /* easy */
1960 /* Copy a 1 octet sequence from the tvbuff
1961 * which represents a char, and convert
1962 * it to an char value.
1963 * offset is then incremented by 1, to indicate the 1 octet which
1964 * has been processed.
1967 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1970 val = tvb_get_guint8(tvb, *offset); /* easy */
1978 * Floating Point Data Type double IEEE 754-1985
1980 * Copy an 8 octet sequence from the tvbuff
1981 * which represents a double value, and convert
1982 * it to a double value, taking into account byte order.
1983 * offset is first incremented so that it falls on a proper alignment
1984 * boundary for double values.
1985 * offset is then incremented by 8, to indicate the 8 octets which
1986 * have been processed.
1989 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1993 /* double values must be aligned on a 8 byte boundary */
1995 while( ( (*offset + boundary) % 8) != 0)
1998 val = (stream_is_big_endian) ? tvb_get_ntohieee_double (tvb, *offset) :
1999 tvb_get_letohieee_double (tvb, *offset);
2007 /* Copy a 4 octet sequence from the tvbuff
2008 * which represents an enum value, and convert
2009 * it to an enum value, taking into account byte order.
2010 * offset is first incremented so that it falls on a proper alignment
2011 * boundary for an enum (4)
2012 * offset is then incremented by 4, to indicate the 4 octets which
2013 * have been processed.
2015 * Enum values are encoded as unsigned long.
2019 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2021 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2027 * Copy an octet sequence from the tvbuff
2028 * which represents a Fixed point decimal type, and create a string representing
2029 * a Fixed point decimal type. There are no alignment restrictions.
2030 * Size and scale of fixed decimal type is determined by IDL.
2032 * digits - IDL specified number of "digits" for this fixed type
2033 * scale - IDL specified "scale" for this fixed type
2036 * eg: typedef fixed <5,2> fixed_t;
2037 * could represent numbers like 123.45, 789.12,
2040 * As the fixed type could be any size, I will not try to fit it into our
2041 * simple types like gdouble or glong etc. I will just create a string buffer holding
2042 * a representation (after scale is applied), and with a decimal point or zero padding
2043 * inserted at the right place if necessary. The string is null terminated
2045 * so string may look like
2048 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2050 * According to spec, digits <= 31
2051 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2054 * User must remember to free the buffer
2059 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2061 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2062 guint32 i ; /* loop */
2063 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2064 /* this does not include sign, decimal point and \0 */
2065 guint32 sindex = 0; /* string index */
2066 gchar *tmpbuf; /* temp buff, holds string without scaling */
2067 guint8 tval; /* temp val storage */
2070 * how many bytes to hold digits and scale (if scale <0)
2072 * eg: fixed <5,2> = 5 digits
2073 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2077 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2081 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2083 slen = digits; /* digits */
2087 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2090 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2093 * Register a cleanup function in case on of our tvbuff accesses
2094 * throws an exception. We need to clean up tmpbuf.
2096 CLEANUP_PUSH(g_free, tmpbuf);
2098 /* If even , grab 1st dig */
2100 if (!(digits & 0x01)) {
2101 tval = get_CDR_octet(tvb,offset);
2103 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2105 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2110 * Loop, but stop BEFORE we hit last digit and sign
2111 * if digits = 1 or 2, then this part is skipped
2115 for(i=0; i< ((digits-1)/2 ); i++) {
2116 tval = get_CDR_octet(tvb,offset);
2118 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2121 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2123 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2130 printf("giop:get_CDR_fixed(): before last digit \n");
2134 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2136 tval = get_CDR_octet(tvb,offset);
2138 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2140 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2143 sign = tval & 0x0f; /* get sign */
2145 /* So now, we have all digits in an array, and the sign byte
2146 * so lets generate a printable string, taking into account the scale
2150 sindex = 0; /* reset */
2151 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2152 * \0 -- TODO check slen is reasonable first */
2154 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2159 (*seq)[sindex] = '+'; /* put sign in first string position */
2162 (*seq)[sindex] = '-';
2165 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2166 (*seq)[sindex] = '*'; /* flag as sign unkown */
2172 /* Add decimal point or padding 0's, depending if scale is positive or
2173 * negative, respectively
2177 for (i=0; i<digits-scale; i++) {
2178 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2182 (*seq)[sindex] = '.'; /* decimal point */
2185 for (i=digits-scale; i<digits; i++) {
2186 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2190 (*seq)[sindex] = '\0'; /* string terminator */
2194 /* negative scale, dump digits and pad out with 0's */
2196 for (i=0; i<digits-scale; i++) {
2198 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2200 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2205 (*seq)[sindex] = '\0'; /* string terminator */
2210 * We're done with tmpbuf, so we can call the cleanup handler to free
2211 * it, and then pop the cleanup handler.
2213 CLEANUP_CALL_AND_POP;
2216 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2226 * Floating Point Data Type float IEEE 754-1985
2228 * Copy an 4 octet sequence from the tvbuff
2229 * which represents a float value, and convert
2230 * it to a float value, taking into account byte order.
2231 * offset is first incremented so that it falls on a proper alignment
2232 * boundary for float values.
2233 * offset is then incremented by 4, to indicate the 4 octets which
2234 * have been processed.
2237 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2241 /* float values must be aligned on a 4 byte boundary */
2243 while( ( (*offset + boundary) % 4) != 0)
2246 val = (stream_is_big_endian) ? tvb_get_ntohieee_float (tvb, *offset) :
2247 tvb_get_letohieee_float (tvb, *offset);
2256 * Decode an Interface type, and display it on the tree.
2259 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2260 gboolean stream_is_big_endian, int boundary) {
2263 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2269 /* Copy a 4 octet sequence from the tvbuff
2270 * which represents a signed long value, and convert
2271 * it to an signed long vaule, taking into account byte order.
2272 * offset is first incremented so that it falls on a proper alignment
2273 * boundary for long values.
2274 * offset is then incremented by 4, to indicate the 4 octets which
2275 * have been processed.
2278 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2282 /* unsigned long values must be aligned on a 4 byte boundary */
2283 while( ( (*offset + boundary) % 4) != 0)
2286 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2287 tvb_get_letohl (tvb, *offset);
2294 * Decode an Object type, and display it on the tree.
2297 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2298 gboolean stream_is_big_endian, int boundary) {
2300 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2306 /* Copy a 1 octet sequence from the tvbuff
2307 * which represents a octet, and convert
2308 * it to an octet value.
2309 * offset is then incremented by 1, to indicate the 1 octet which
2310 * has been processed.
2313 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2316 val = tvb_get_guint8(tvb, *offset); /* easy */
2322 /* Copy a sequence of octets from the tvbuff.
2323 * Caller of this function must remember to free the
2324 * array pointed to by seq.
2325 * This function also increments offset by len.
2328 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, guint32 len) {
2331 * Make sure that the entire sequence of octets is in the buffer before
2332 * allocating the buffer, so that we don't have to worry about freeing
2333 * the buffer, and so that we don't try to allocate a buffer bigger
2334 * than the data we'll actually be copying, and thus don't run the risk
2335 * of crashing if the buffer is *so* big that we fail to allocate it
2336 * and "g_new0()" aborts.
2338 tvb_ensure_bytes_exist(tvb, *offset, len);
2341 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2342 * do what we do now, and null-terminate the string (which also means
2343 * we don't need to zero out the entire allocation, just the last byte)?
2345 *seq = g_new0(gchar, len + 1);
2346 tvb_memcpy( tvb, *seq, *offset, len);
2351 /* Copy a 2 octet sequence from the tvbuff
2352 * which represents a signed short value, and convert
2353 * it to a signed short value, taking into account byte order.
2354 * offset is first incremented so that it falls on a proper alignment
2355 * boundary for short values.
2356 * offset is then incremented by 2, to indicate the 2 octets which
2357 * have been processed.
2360 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2364 /* short values must be aligned on a 2 byte boundary */
2365 while( ( (*offset + boundary) % 2) != 0)
2368 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2369 tvb_get_letohs (tvb, *offset);
2377 /* Copy an octet sequence from the tvbuff
2378 * which represents a string, and convert
2379 * it to an string value, taking into account byte order.
2380 * offset is first incremented so that it falls on a proper alignment
2381 * boundary for string values. (begins with an unsigned long LI)
2383 * String sequence is copied to a buffer "seq". This must
2384 * be freed by the calling program.
2385 * offset is then incremented, to indicate the octets which
2386 * have been processed.
2388 * returns number of octets in the sequence
2390 * Note: This function only supports single byte encoding at the
2391 * moment until I get a handle on multibyte encoding etc.
2396 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2401 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2404 (*offset)++; /* must step past \0 delimiter */
2408 get_CDR_octet_seq(tvb, seq, offset, slength);
2410 *seq = g_strdup(""); /* zero-length string */
2413 return slength; /* return length */
2417 /* Process a sequence of octets that represent the
2418 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2420 * This function also increments offset to the correct position.
2422 * It will parse the TypeCode and output data to the "tree" provided
2425 * It returns a guint32 representing a TCKind value.
2428 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2429 gboolean stream_is_big_endian, int boundary,
2430 MessageHeader * header ) {
2433 gint16 s_octet2; /* signed int16 */
2434 guint16 u_octet2; /* unsigned int16 */
2435 guint32 u_octet4; /* unsigned int32 */
2437 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2439 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2440 *offset-sizeof(val),4,val);
2443 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2446 case tk_null: /* empty parameter list */
2448 case tk_void: /* empty parameter list */
2450 case tk_short: /* empty parameter list */
2452 case tk_long: /* empty parameter list */
2454 case tk_ushort: /* empty parameter list */
2456 case tk_ulong: /* empty parameter list */
2458 case tk_float: /* empty parameter list */
2460 case tk_double: /* empty parameter list */
2462 case tk_boolean: /* empty parameter list */
2464 case tk_char: /* empty parameter list */
2466 case tk_octet: /* empty parameter list */
2468 case tk_any: /* empty parameter list */
2470 case tk_TypeCode: /* empty parameter list */
2472 case tk_Principal: /* empty parameter list */
2474 case tk_objref: /* complex parameter list */
2475 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary);
2477 case tk_struct: /* complex parameter list */
2478 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2480 case tk_union: /* complex parameter list */
2481 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2483 case tk_enum: /* complex parameter list */
2484 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary);
2487 case tk_string: /* simple parameter list */
2488 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2490 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2491 *offset-sizeof(u_octet4),4,u_octet4);
2495 case tk_sequence: /* complex parameter list */
2496 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2498 case tk_array: /* complex parameter list */
2499 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2501 case tk_alias: /* complex parameter list */
2502 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2504 case tk_except: /* complex parameter list */
2505 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2507 case tk_longlong: /* empty parameter list */
2509 case tk_ulonglong: /* empty parameter list */
2511 case tk_longdouble: /* empty parameter list */
2513 case tk_wchar: /* empty parameter list */
2515 case tk_wstring: /* simple parameter list */
2516 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2518 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2519 *offset-sizeof(u_octet4),4,u_octet4);
2523 case tk_fixed: /* simple parameter list */
2524 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2526 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2527 *offset-sizeof(u_octet2),2,u_octet2);
2530 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2532 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2533 *offset-sizeof(s_octet2),2,s_octet2);
2537 case tk_value: /* complex parameter list */
2538 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2540 case tk_value_box: /* complex parameter list */
2541 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2543 case tk_native: /* complex parameter list */
2544 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary);
2546 case tk_abstract_interface: /* complex parameter list */
2547 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary );
2550 g_warning("giop: Unknown TCKind %u \n", val);
2559 /* Copy a 4 octet sequence from the tvbuff
2560 * which represents an unsigned long value, and convert
2561 * it to an unsigned long vaule, taking into account byte order.
2562 * offset is first incremented so that it falls on a proper alignment
2563 * boundary for unsigned long values.
2564 * offset is then incremented by 4, to indicate the 4 octets which
2565 * have been processed.
2568 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2572 /* unsigned long values must be aligned on a 4 byte boundary */
2573 while( ( (*offset + boundary) % 4) != 0)
2576 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2577 tvb_get_letohl (tvb, *offset);
2584 /* Copy a 2 octet sequence from the tvbuff
2585 * which represents an unsigned short value, and convert
2586 * it to an unsigned short value, taking into account byte order.
2587 * offset is first incremented so that it falls on a proper alignment
2588 * boundary for unsigned short values.
2589 * offset is then incremented by 2, to indicate the 2 octets which
2590 * have been processed.
2593 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2597 /* unsigned short values must be aligned on a 2 byte boundary */
2598 while( ( (*offset + boundary) % 2) != 0)
2601 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2602 tvb_get_letohs (tvb, *offset);
2610 /* Copy a wchar from the tvbuff.
2611 * Caller of this function must remember to free the
2612 * array pointed to by seq.
2613 * This function also increments offset according to
2616 * For GIOP 1.1 read 2 octets and return size -2. The
2617 * negation means there is no size element in the packet
2618 * and therefore no size to add to the tree.
2620 * For GIOP 1.2 read size of wchar and the size
2621 * octets. size is returned as a gint8.
2623 * For both GIOP versions the wchar is returned
2624 * as a printable string.
2628 /* NOTE: This is very primitive in that it just reads
2629 * the wchar as a series of octets and returns them
2630 * to the user. No translation is attempted based on
2631 * byte orientation, nor on code set. I.e it only
2632 * really reads past the wchar and sets the offset
2636 /* The "decoding" is done according to CORBA chapter 15.
2637 * Wchar is not supported for GIOP 1.0.
2640 gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2645 /* CORBA chapter 15:
2646 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2647 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2648 * followed by the elements of the octet sequence representing
2649 * the encoded value of the wchar.
2652 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2653 slength = 2; /* set for GIOP 1.1 length in octets */
2655 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2656 slength = get_CDR_octet(tvb,offset);
2659 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2660 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2662 /* now turn octets (wchar) into something that can be printed by the user */
2663 *seq = make_printable_string(raw_wstring, slength);
2665 g_free(raw_wstring);
2668 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2669 if (header->GIOP_version.minor < 2)
2672 return slength; /* return length */
2677 /* Copy a wstring 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
2681 * wstring length. length is returned as guint32
2684 /* NOTE: This is very primitive in that it just reads
2685 * the wstring as a series of octets and returns them
2686 * to the user. No translation is attempted based on
2687 * byte orientation, nor on code set. I.e it only
2688 * really reads past the wstring and sets the offset
2692 /* The "decoding" is done according to CORBA chapter 15.
2693 * Wstring is not supported for GIOP 1.0.
2697 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2698 int boundary, MessageHeader * header) {
2703 /* CORBA chapter 15:
2704 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2705 * length and string are NUL terminated (length???).
2706 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2710 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2712 /* get length, same for all GIOP versions,
2713 * although for 1.2 CORBA doesnt say, so assume.
2715 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2719 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2720 slength = 5; /* better than core dumping during debug */
2724 if (header->GIOP_version.minor < 2) {
2726 (*offset)++; /* must step past \0 delimiter */
2728 /* assume length is number of characters and not octets, spec not clear */
2729 slength = slength * 2; /* length in octets is 2 * wstring length */
2733 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2735 /* now turn octets (wstring) into something that can be printed by the user */
2736 *seq = make_printable_string(raw_wstring, slength);
2738 g_free(raw_wstring);
2741 return slength; /* return length */
2748 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2750 * typedef short AddressingDisposition;
2751 * const short KeyAddr = 0;
2752 * const short ProfileAddr = 1;
2753 * const short ReferenceAddr = 2;
2754 * struct IORAddressingInfo {
2755 * unsigned long selected_profile_index;
2759 * union TargetAddress switch (AddressingDisposition) {
2760 * case KeyAddr: sequence <octet> object_key;
2761 * case ProfileAddr: IOP::TaggedProfile profile;
2762 * case ReferenceAddr: IORAddressingInfo ior;
2767 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2768 gboolean stream_is_big_endian)
2770 guint16 discriminant;
2772 gchar *p_object_key;
2776 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2779 proto_tree_add_text (tree, tvb, *offset -2, 2,
2780 "TargetAddress Discriminant: %u", discriminant);
2783 switch (discriminant)
2785 case 0: /* KeyAddr */
2786 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2789 proto_tree_add_text (tree, tvb, *offset -4, 4,
2790 "KeyAddr (object key length): %u", len);
2795 get_CDR_octet_seq(tvb, &object_key, offset, len);
2796 p_object_key = make_printable_string( object_key, len );
2800 proto_tree_add_text (tree, tvb, *offset -len, len,
2801 "KeyAddr (object key): %s", p_object_key);
2803 g_free( p_object_key );
2804 g_free( object_key );
2807 case 1: /* ProfileAddr */
2808 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2809 stream_is_big_endian, NULL);
2811 case 2: /* ReferenceAddr */
2812 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2816 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2817 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2820 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2828 dissect_reply_body (tvbuff_t *tvb, u_int offset, packet_info *pinfo,
2829 proto_tree *tree, gboolean stream_is_big_endian,
2830 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2832 u_int sequence_length;
2833 gboolean exres = FALSE; /* result of trying explicit dissectors */
2834 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2837 * comp_req_list stuff
2840 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2844 switch (reply_status)
2846 case SYSTEM_EXCEPTION:
2848 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2851 case USER_EXCEPTION:
2853 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2857 proto_tree_add_text(tree, tvb, offset-4, 4,
2858 "Exception length: %u", sequence_length);
2860 if (sequence_length != 0)
2864 proto_tree_add_text(tree, tvb, offset, sequence_length,
2866 tvb_format_text(tvb, offset, sequence_length));
2870 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2872 /* read exception id from buffer and store in*/
2874 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2880 offset += sequence_length;
2886 * Now just fall through to the NO_EXCEPTION part
2887 * as this is common .
2895 /* lookup MFN in hash directly */
2897 mfn = get_mfn_from_fn(pinfo->fd->num);
2899 if (mfn == pinfo->fd->num)
2900 return; /* no matching frame number, what am I */
2902 /* get entry for this MFN */
2903 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2906 return; /* no matching entry */
2910 * If this packet is a REPLY to a RESOLVE(request)
2912 * TODO - make this lookup faster -- FS
2915 if (!strcmp(giop_op_resolve,entry->operation)) {
2916 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2920 /* TODO -- Put stuff here for other "interesting operations" */
2924 * Call sub dissector.
2925 * First try an find a explicit sub_dissector, then if that
2926 * fails, try the heuristic method.
2931 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
2934 /* Only call heuristic if no explicit dixxector was found */
2937 try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
2943 case LOCATION_FORWARD:
2944 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2948 case LOCATION_FORWARD_PERM:
2949 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2953 case NEEDS_ADDRESSING_MODE: {
2955 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2957 proto_tree_add_text (tree, tvb, offset -2, 2,
2958 "AddressingDisposition: %u", addr_disp);
2966 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
2972 g_free(repoid); /* free resource */
2982 /* The format of the Reply Header for GIOP 1.0 and 1.1
2983 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
2985 struct ReplyHeader_1_0 {
2986 IOP::ServiceContextList service_context;
2987 unsigned long request_id;
2988 ReplyStatusType_1_0 reply_status;
2992 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
2993 MessageHeader * header,
2994 gboolean stream_is_big_endian) {
2998 guint32 reply_status;
2999 proto_tree *reply_tree = NULL;
3001 guint32 mfn; /* matching frame number */
3004 tf = proto_tree_add_text (tree, tvb, offset, -1,
3005 "General Inter-ORB Protocol Reply");
3006 if (reply_tree == NULL)
3008 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3014 * Decode IOP::ServiceContextList
3017 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3019 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3021 if (check_col(pinfo->cinfo, COL_INFO)) {
3022 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3026 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3027 "Request id: %u", request_id);
3030 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3032 if (check_col(pinfo->cinfo, COL_INFO)) {
3033 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3034 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3039 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3041 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3046 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3049 if (! pinfo->fd->flags.visited) {
3050 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3051 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3052 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3056 header->req_id = request_id; /* save for sub dissector */
3057 header->rep_status = reply_status; /* save for sub dissector */
3059 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3060 reply_status, header,tree);
3065 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3066 * and 1.1 header, only the fields have been rearranged. From Section
3067 * 15.4.3.1 of the CORBA 2.4 specification:
3069 * struct ReplyHeader_1_2 {
3070 * unsigned long request_id;
3071 * ReplyStatusType_1_2 reply_status;
3072 * IOP:ServiceContextList service_context;
3076 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3078 MessageHeader * header,
3079 gboolean stream_is_big_endian) {
3083 guint32 reply_status;
3084 proto_tree *reply_tree = NULL;
3086 guint32 mfn; /* matching frame number */
3089 tf = proto_tree_add_text (tree, tvb, offset, -1,
3090 "General Inter-ORB Protocol Reply");
3091 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3094 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3096 if (check_col(pinfo->cinfo, COL_INFO)) {
3097 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3101 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3102 "Request id: %u", request_id);
3105 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3107 if (check_col(pinfo->cinfo, COL_INFO)) {
3108 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3109 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3114 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3116 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3121 * Decode IOP::ServiceContextList
3124 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3127 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3130 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3133 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3136 if (! pinfo->fd->flags.visited) {
3137 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3138 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3139 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3144 * Add header to argument list so sub dissector can get header info.
3147 header->req_id = request_id; /* save for sub dissector */
3148 header->rep_status = reply_status; /* save for sub dissector */
3150 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3151 reply_status,header,tree);
3157 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3159 gboolean stream_is_big_endian) {
3163 proto_tree *cancel_request_tree = NULL;
3167 tf = proto_tree_add_text (tree, tvb, offset, -1,
3168 "General Inter-ORB Protocol CancelRequest");
3169 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3172 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3174 if (check_col(pinfo->cinfo, COL_INFO)) {
3175 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3179 proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4,
3180 "Request id: %u", request_id);
3186 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3187 * in section 15.4.2.1 of the CORBA 2.4 specification.
3189 * struct RequestHeader{
3190 * IOP::ServiceContextList service_context;
3191 * unsigned long request_id;
3192 * boolean response_expected;
3193 * octet reserved[3]; // Only in GIOP 1.1
3194 * sequence<octet> object_key;
3196 * CORBA::OctetSeq requesting_principal;
3200 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3202 MessageHeader * header, gboolean stream_is_big_endian)
3208 guint32 objkey_len = 0; /* object key length */
3209 gchar *objkey = NULL; /* object key sequence */
3210 gchar *print_objkey; /* printable object key sequence */
3211 gboolean exres = FALSE; /* result of trying explicit dissectors */
3214 gchar *requesting_principal;
3215 gchar *print_requesting_principal;
3216 guint8 response_expected;
3218 proto_tree *request_tree = NULL;
3221 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3226 tf = proto_tree_add_text (tree, tvb, offset, -1,
3227 "General Inter-ORB Protocol Request");
3228 if (request_tree == NULL)
3230 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3239 * Decode IOP::ServiceContextList
3242 decode_ServiceContextList(tvb, request_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3245 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3246 if (check_col(pinfo->cinfo, COL_INFO))
3248 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3252 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3253 "Request id: %u", request_id);
3256 response_expected = tvb_get_guint8( tvb, offset );
3258 if (check_col(pinfo->cinfo, COL_INFO))
3260 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3261 response_expected ? "two-way" : "one-way");
3265 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3266 "Response expected: %u", response_expected);
3269 if( header->GIOP_version.minor > 0)
3271 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3274 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3275 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3282 /* Length of object_key sequence */
3283 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3288 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3289 /**/ "Object Key length: %u", objkey_len);
3294 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3296 print_objkey = make_printable_string(objkey, objkey_len);
3300 proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
3301 /**/ "Object Key: %s", print_objkey);
3305 g_free( print_objkey );
3309 * Register a cleanup function in case on of our tvbuff accesses
3310 * throws an exception. We need to clean up objkey.
3312 CLEANUP_PUSH(g_free, objkey);
3314 /* length of operation string and string */
3315 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3318 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3319 /**/ "Operation length: %u", len);
3324 if (check_col(pinfo->cinfo, COL_INFO))
3326 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3330 proto_tree_add_text (request_tree, tvb, offset - len, len,
3331 /**/ "Operation: %s", operation);
3337 * Register a cleanup function in case on of our tvbuff accesses
3338 * throws an exception. We need to clean up operation.
3340 CLEANUP_PUSH(g_free, operation);
3342 /* length of requesting_principal string */
3343 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3346 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3347 /**/ "Requesting Principal Length: %u", len);
3352 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3354 print_requesting_principal = make_printable_string(requesting_principal, len);
3358 proto_tree_add_text (request_tree, tvb, offset - len, len,
3359 /**/ "Requesting Principal: %s", print_requesting_principal);
3363 g_free( print_requesting_principal );
3364 g_free( requesting_principal );
3369 * Save FN,reqid,and operation for later. Add sub_handle later.
3370 * But only if user is NOT clicking.
3373 if (! pinfo->fd->flags.visited)
3374 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3375 request_id,operation,NULL);
3379 * Call subdissector here before freeing "operation" and "key"
3380 * pass request_id also.
3381 * First try an find an explicit sub_dissector, then if that
3382 * fails, try the heuristic method.
3387 header->req_id = request_id; /* save for sub dissector */
3388 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3392 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3395 /* Only call heuristic if no explicit dissector was found */
3398 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3403 * We're done with operation, so we can call the cleanup handler to free
3404 * it, and then pop the cleanup handler.
3406 CLEANUP_CALL_AND_POP;
3409 * We're done with objkey, so we can call the cleanup handler to free
3410 * it, and then pop the cleanup handler.
3412 CLEANUP_CALL_AND_POP;
3416 /** The format of a GIOP 1.2 RequestHeader message is
3417 * (CORBA 2.4, sec. 15.4.2):
3419 * struct RequestHeader_1_2 {
3420 * unsigned long request_id;
3421 * octet response_flags;
3422 * octet reserved[3];
3423 * TargetAddress target;
3425 * IOP::ServiceContextList service_context;
3426 * // requesting_principal not in GIOP 1.2
3430 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3432 MessageHeader * header, gboolean stream_is_big_endian)
3437 guint8 response_flags;
3439 gchar *operation = NULL;
3440 proto_tree *request_tree = NULL;
3442 gboolean exres = FALSE; /* result of trying explicit dissectors */
3444 gchar *repoid = NULL;
3449 tf = proto_tree_add_text (tree, tvb, offset, -1,
3450 "General Inter-ORB Protocol Request");
3451 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3454 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3455 if (check_col(pinfo->cinfo, COL_INFO))
3457 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3461 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3462 "Request id: %u", request_id);
3465 response_flags = tvb_get_guint8( tvb, offset );
3469 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3470 "Response flags: %s (%u)",
3471 match_strval(response_flags, sync_scope),
3475 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3478 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3479 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3483 dissect_target_address(tvb, pinfo, &offset, request_tree, stream_is_big_endian);
3485 /* length of operation string */
3486 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3489 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3490 /**/ "Operation length: %u", len);
3495 if (check_col(pinfo->cinfo, COL_INFO))
3497 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3501 proto_tree_add_text (request_tree, tvb, offset - len, len,
3502 /**/ "Operation: %s", operation);
3509 * Register a cleanup function in case on of our tvbuff accesses
3510 * throws an exception. We need to clean up operation.
3512 CLEANUP_PUSH(g_free, operation);
3515 * Decode IOP::ServiceContextList
3518 decode_ServiceContextList(tvb, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3521 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3522 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3523 * GIOP octet stream start.
3526 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3529 * Save FN,reqid,and operation for later. Add sub_handle later.
3530 * But only if user is NOT clicking.
3533 if (! pinfo->fd->flags.visited)
3534 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3535 request_id,operation,NULL);
3539 * Call sub dissector.
3540 * First try an find a explicit sub_dissector, then if that
3541 * fails, try the heuristic method.
3546 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3549 /* Only call heuristic if no explicit dissector was found */
3552 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3557 * We're done with operation, so we can call the cleanup handler to free
3558 * it, and then pop the cleanup handler.
3560 CLEANUP_CALL_AND_POP;
3564 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3565 proto_tree * tree, MessageHeader * header,
3566 gboolean stream_is_big_endian)
3572 gchar *p_object_key;
3573 proto_tree *locate_request_tree = NULL;
3578 tf = proto_tree_add_text (tree, tvb, offset, -1,
3579 "General Inter-ORB Locate Request");
3580 if (locate_request_tree == NULL)
3582 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3587 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3588 if (check_col(pinfo->cinfo, COL_INFO))
3590 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3592 if (locate_request_tree)
3594 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3595 "Request id: %u", request_id);
3598 if(header->GIOP_version.minor < 2)
3600 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3601 if (locate_request_tree)
3603 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3604 "Object Key length: %u", len);
3608 get_CDR_octet_seq(tvb, &object_key, &offset, len);
3610 p_object_key = make_printable_string(object_key, len);
3612 if(locate_request_tree)
3615 proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
3616 "Object Key: %s", p_object_key);
3619 g_free(p_object_key);
3623 else /* GIOP 1.2 and higher */
3625 dissect_target_address(tvb, pinfo, &offset, locate_request_tree,
3626 stream_is_big_endian);
3632 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3633 proto_tree * tree, MessageHeader * header,
3634 gboolean stream_is_big_endian)
3638 guint32 locate_status;
3641 proto_tree *locate_reply_tree = NULL;
3646 tf = proto_tree_add_text (tree, tvb, offset, -1,
3647 "General Inter-ORB Locate Reply");
3648 if (locate_reply_tree == NULL)
3650 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3655 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3656 if (check_col(pinfo->cinfo, COL_INFO))
3658 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3660 if (locate_reply_tree)
3662 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3663 "Request id: %u", request_id);
3666 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3667 if (locate_reply_tree)
3669 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3670 "Locate status: %s",
3671 match_strval(locate_status, giop_locate_status_types)
3675 /* Decode the LocateReply body.
3677 * For GIOP 1.0 and 1.1 body immediately follows header.
3678 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3682 if (header->GIOP_version.minor > 1) {
3683 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3687 switch(locate_status) {
3688 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3689 case OBJECT_FORWARD_PERM:
3690 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3692 case LOC_SYSTEM_EXCEPTION:
3693 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3695 case LOC_NEEDS_ADDRESSING_MODE:
3696 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3697 if(locate_reply_tree) {
3698 proto_tree_add_text (tree, tvb, offset -2, 2,
3699 "AddressingDisposition: %u", addr_disp);
3702 default: /* others have no reply body */
3709 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3710 gboolean stream_is_big_endian)
3714 proto_tree *fragment_tree = NULL;
3719 tf = proto_tree_add_text (tree, tvb, offset, -1,
3720 "General Inter-ORB Fragment");
3721 if (fragment_tree == NULL)
3723 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3728 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3729 if (check_col(pinfo->cinfo, COL_INFO))
3731 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3735 proto_tree_add_text (fragment_tree, tvb, offset-4, 4,
3736 "Request id: %u", request_id);
3742 /* Main entry point */
3744 gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3746 MessageHeader header;
3747 tvbuff_t *giop_header_tvb;
3748 tvbuff_t *payload_tvb;
3750 proto_tree *clnp_tree = NULL;
3753 u_int minor_version;
3754 gboolean stream_is_big_endian;
3760 giop_dump_collection(cd_module_hash);
3761 giop_dump_collection(cd_objkey_hash);
3762 giop_dump_collection(cd_heuristic_users);
3763 giop_dump_collection(cd_complete_reply_hash);
3764 giop_dump_collection(cd_complete_request_list);
3767 header.exception_id = NULL;
3769 /* check magic number and version */
3772 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
3774 if (tvb_length_remaining(tvb, 0) < GIOP_HEADER_SIZE)
3776 /* Not enough data captured to hold the GIOP header; don't try
3777 to interpret it as GIOP. */
3781 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3782 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3785 * because I have added extra elements in MessageHeader struct
3786 * for sub dissectors. -- FS
3789 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3791 if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
3793 /* Not a GIOP message. */
3798 if (check_col (pinfo->cinfo, COL_PROTOCOL))
3800 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3803 if (header.GIOP_version.major != GIOP_MAJOR ||
3804 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3806 /* Bad version number; should we note that and dissect the rest
3807 as data, or should we return FALSE on the theory that it
3808 might have been some other packet that happened to begin with
3809 "GIOP"? We shouldn't do *both*, so we return TRUE, for now.
3810 If we should return FALSE, we should do so *without* setting
3811 the "Info" column, *without* setting the "Protocol" column,
3812 and *without* adding anything to the protocol tree. */
3814 if (check_col (pinfo->cinfo, COL_INFO))
3816 col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3817 header.GIOP_version.major, header.GIOP_version.minor);
3821 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3822 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3823 proto_tree_add_text (clnp_tree, giop_header_tvb, 0, -1,
3824 "Version %u.%u not supported",
3825 header.GIOP_version.major,
3826 header.GIOP_version.minor);
3828 call_dissector(data_handle,payload_tvb, pinfo, tree);
3832 if (check_col (pinfo->cinfo, COL_INFO))
3834 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3835 header.GIOP_version.major, header.GIOP_version.minor,
3836 val_to_str(header.message_type, giop_message_types,
3837 "Unknown message type (0x%02x)"));
3840 stream_is_big_endian = is_big_endian (&header);
3842 if (stream_is_big_endian)
3843 message_size = pntohl (&header.message_size);
3845 message_size = pletohl (&header.message_size);
3849 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, 12, FALSE);
3850 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3851 proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3852 "Magic number: %s", GIOP_MAGIC);
3853 proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3855 header.GIOP_version.major,
3856 header.GIOP_version.minor);
3857 switch (minor_version)
3861 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3862 "Flags: 0x%02x (%s %s)",
3864 (stream_is_big_endian) ? "big-endian" : "little-endian",
3865 (header.flags & 0x02) ? " fragment" : "");
3868 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3869 "Byte ordering: %s-endian",
3870 (stream_is_big_endian) ? "big" : "little");
3874 } /* minor_version */
3876 proto_tree_add_uint_format (clnp_tree,
3877 hf_giop_message_type,
3878 giop_header_tvb, 7, 1,
3879 header.message_type,
3880 "Message type: %s", match_strval(header.message_type, giop_message_types));
3882 proto_tree_add_uint (clnp_tree,
3883 hf_giop_message_size,
3884 giop_header_tvb, 8, 4, message_size);
3889 if (check_col (pinfo->cinfo, COL_INFO))
3891 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3892 header.GIOP_version.major, header.GIOP_version.minor,
3893 match_strval(header.message_type, giop_message_types));
3897 switch (header.message_type)
3901 if(header.GIOP_version.minor < 2)
3903 dissect_giop_request_1_1 (payload_tvb, pinfo, tree,
3904 &header, stream_is_big_endian);
3908 dissect_giop_request_1_2 (payload_tvb, pinfo, tree,
3909 &header, stream_is_big_endian);
3916 if(header.GIOP_version.minor < 2)
3918 dissect_giop_reply (payload_tvb, pinfo, tree, &header,
3919 stream_is_big_endian);
3923 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree,
3924 &header, stream_is_big_endian);
3928 dissect_giop_cancel_request(payload_tvb, pinfo, tree,
3929 stream_is_big_endian);
3932 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
3933 stream_is_big_endian);
3936 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
3937 stream_is_big_endian);
3940 dissect_giop_fragment(payload_tvb, pinfo, tree,
3941 stream_is_big_endian);
3946 } /* switch message_type */
3950 * XXX - we should catch exceptions here, so that we can free
3951 * this if an exception is thrown.
3952 * We'd then have to forward the exception.
3954 if (header.exception_id != NULL)
3955 g_free(header.exception_id);
3961 proto_register_giop (void)
3963 static hf_register_info hf[] = {
3964 { &hf_giop_message_type,
3965 { "Message type", "giop.type",
3966 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
3969 { &hf_giop_message_size,
3970 { "Message size", "giop.len",
3971 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3975 { "Repository ID", "giop.repoid",
3976 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
3979 { &hf_giop_string_length,
3980 { "String Length", "giop.strlen",
3981 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3984 { &hf_giop_sequence_length,
3985 { "Sequence Length", "giop.seqlen",
3986 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3989 { &hf_giop_profile_id,
3990 { "Profile ID", "giop.profid",
3991 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
3996 { "IOR::type_id", "giop.typeid",
3997 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4000 { &hf_giop_iiop_v_maj,
4001 { "IIOP Major Version", "giop.iiop_vmaj",
4002 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4005 { &hf_giop_iiop_v_min,
4006 { "IIOP Minor Version", "giop.iiop_vmin",
4007 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4010 { &hf_giop_endianess,
4011 { "Endianess", "giop.endianess",
4012 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4015 { &hf_giop_IIOP_tag,
4016 { "IIOP Component TAG", "giop.iioptag",
4017 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4021 { "IOR Profile TAG", "giop.iortag",
4022 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4026 { "TypeCode enum", "giop.TCKind",
4027 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4030 { &hf_giop_typecode_count,
4031 { "TypeCode count", "giop.tccount",
4032 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4035 { &hf_giop_typecode_default_used,
4036 { "default_used", "giop.tcdefault_used",
4037 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4040 { &hf_giop_typecode_digits,
4041 { "Digits", "giop.tcdigits",
4042 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4046 { &hf_giop_typecode_length,
4047 { "Length", "giop.tclength",
4048 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4051 { &hf_giop_typecode_max_length,
4052 { "Maximum length", "giop.tcmaxlen",
4053 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4056 { &hf_giop_typecode_member_name,
4057 { "TypeCode member name", "giop.tcmemname",
4058 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4061 { &hf_giop_typecode_name,
4062 { "TypeCode name", "giop.tcname",
4063 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4066 { &hf_giop_typecode_scale,
4067 { "Scale", "giop.tcscale",
4068 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4071 { &hf_giop_typecode_ValueModifier,
4072 { "ValueModifier", "giop.tcValueModifier",
4073 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4076 { &hf_giop_typecode_Visibility,
4077 { "Visibility", "giop.tcVisibility",
4078 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4083 { &hf_giop_type_boolean,
4084 { "TypeCode boolean data", "giop.tcboolean",
4085 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4088 { &hf_giop_type_char,
4089 { "TypeCode char data", "giop.tcchar",
4090 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4093 { &hf_giop_type_double,
4094 { "TypeCode double data", "giop.tcdouble",
4095 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4098 { &hf_giop_type_enum,
4099 { "TypeCode enum data", "giop.tcenumdata",
4100 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4104 * float as double ?? -- FIX
4107 { &hf_giop_type_float,
4108 { "TypeCode float data", "giop.tcfloat",
4109 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4112 { &hf_giop_type_long,
4113 { "TypeCode long data", "giop.tclongdata",
4114 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4117 { &hf_giop_type_octet,
4118 { "TypeCode octet data", "giop.tcoctet",
4119 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4122 { &hf_giop_type_short,
4123 { "TypeCode short data", "giop.tcshortdata",
4124 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4127 { &hf_giop_type_string,
4128 { "TypeCode string data", "giop.tcstring",
4129 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4132 { &hf_giop_type_ulong,
4133 { "TypeCode ulong data", "giop.tculongdata",
4134 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4137 { &hf_giop_type_ushort,
4138 { "TypeCode ushort data", "giop.tcushortdata",
4139 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4143 * IIOP Module - Chapter 15.10.2
4146 { &hf_giop_iiop_host,
4147 { "IIOP::Profile_host", "giop.iiop.host",
4148 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4152 { &hf_giop_iiop_port,
4153 { "IIOP::Profile_port", "giop.iiop.port",
4154 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4159 * IIOP ServiceContext
4162 { &hf_giop_iop_vscid,
4163 { "VSCID", "giop.iiop.vscid",
4164 FT_UINT32, BASE_HEX, NULL, 0xfffff000, "", HFILL }
4168 { &hf_giop_iop_scid,
4169 { "SCID", "giop.iiop.scid",
4170 FT_UINT32, BASE_HEX, NULL, 0x00000fff, "", HFILL }
4177 static gint *ett[] = {
4181 &ett_giop_cancel_request,
4182 &ett_giop_locate_request,
4183 &ett_giop_locate_reply,
4189 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4191 proto_register_field_array (proto_giop, hf, array_length (hf));
4192 proto_register_subtree_array (ett, array_length (ett));
4195 /* register init routine */
4197 register_init_routine( &giop_init); /* any init stuff */
4200 * Init the giop user module hash tables here, as giop users
4201 * will populate it via register_giop_user_module BEFORE my
4202 * own giop_init() is called.
4205 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4207 giop_module_keys = g_mem_chunk_new("giop_module_keys",
4208 sizeof(struct giop_module_key),
4209 giop_module_init_count * sizeof(struct giop_module_key),
4212 giop_module_vals = g_mem_chunk_new("giop_module_vals",
4213 sizeof(struct giop_module_val),
4214 giop_module_init_count * sizeof(struct giop_module_val),
4221 void proto_reg_handoff_giop (void) {
4222 data_handle = find_dissector("data");
4223 heur_dissector_add("tcp", dissect_giop, proto_giop);
4224 /* Support DIOP (GIOP/UDP) */
4225 heur_dissector_add("udp", dissect_giop, proto_giop);
4234 * Ref Corba v2.4.2 Chapter 13
4242 typedef unsigned long ProfileId;
4244 const ProfileId TAG_INTERNET_IOP = 0;
4245 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4247 struct TaggedProfile {
4249 sequence <octet> profile_data;
4254 sequence <TaggedProfile> profiles;
4257 typedef unsigned long ComponentId;
4259 struct TaggedComponent {
4261 sequence <octet> component_data;
4264 typedef sequence <TaggedComponent> MultipleComponentProfile;
4270 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4271 guint32 boundary, gboolean stream_is_big_endian) {
4274 guint32 seqlen_p; /* sequence length of profiles */
4277 proto_tree *tree = NULL; /* IOR tree */
4280 gchar *repobuf; /* for repository ID */
4284 /* create a subtree */
4287 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
4288 tree = proto_item_add_subtree (tf, ett_giop_ior);
4292 /* Get type_id == Repository ID */
4294 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4297 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4298 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4300 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4301 *offset-u_octet4,u_octet4,repobuf);
4306 * Register a cleanup function in case on of our tvbuff accesses
4307 * throws an exception. We need to clean up repobuf.
4308 * We can't free it yet, as we must wait until we have the object
4309 * key, as we have to add both to the hash table.
4311 CLEANUP_PUSH(g_free, repobuf);
4313 /* Now get a sequence of profiles */
4314 /* Get sequence length (number of elements) */
4316 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4318 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4319 *offset-sizeof(seqlen_p),4,seqlen_p);
4323 /* fetch all TaggedProfiles in this sequence */
4325 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4326 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4330 * We're done with repobuf, so we can call the cleanup handler to free
4331 * it, and then pop the cleanup handler.
4333 CLEANUP_CALL_AND_POP;
4337 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4338 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4340 guint32 seqlen_pd; /* sequence length of profile data */
4342 guint32 pidtag; /* profile ID TAG */
4344 gchar *profile_data; /* profile_data pointer */
4345 gchar *p_profile_data; /* printable profile_data pointer */
4347 guint32 new_boundary; /* for encapsulations encountered */
4348 gboolean new_big_endianess; /* for encapsulations encountered */
4350 /* Get ProfileId tag */
4352 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4355 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4356 *offset-sizeof(pidtag),4,pidtag);
4359 /* get sequence length, new endianness and boundary for encapsulation */
4361 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4362 stream_is_big_endian, boundary,
4363 &new_big_endianess, &new_boundary);
4365 /* return if zero length sequence */
4372 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4373 * decode it, otherwise just dump the octet sequence
4375 * also, store IOR in our objectkey hash
4377 * TODO - handle other TAGS
4381 case IOP_TAG_INTERNET_IOP:
4383 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4388 /* fetch all octets in this sequence , but skip endianess */
4390 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4392 /* Make a printable string */
4394 p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4397 proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4398 "Profile Data: %s", p_profile_data);
4401 g_free(p_profile_data);
4403 g_free(profile_data);
4414 * Decode IIOP IOR Profile
4415 * Ref Chap 15.7.2 in Corba Spec
4419 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4420 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4421 gboolean store_flag) {
4423 guint32 i; /* loop index */
4425 guint8 v_major,v_minor; /* IIOP sersion */
4427 guint32 u_octet4; /* u long */
4428 guint16 u_octet2; /* u short */
4429 guint32 seqlen; /* generic sequence length */
4430 guint32 seqlen1; /* generic sequence length */
4431 gchar *objkey; /* object key pointer */
4432 gchar *p_chars; /* printable characters pointer */
4435 /* Get major/minor version */
4437 v_major = get_CDR_octet(tvb,offset);
4438 v_minor = get_CDR_octet(tvb,offset);
4442 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4443 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4444 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4445 *offset-sizeof(v_minor),1,v_minor );
4451 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4454 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4455 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4457 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4458 *offset-u_octet4,u_octet4,buf);
4462 g_free(buf); /* dont forget */
4466 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4469 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4470 *offset-sizeof(u_octet2),2,u_octet2);
4474 /* Object Key - sequence<octet> object_key */
4476 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4479 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4480 *offset-sizeof(seqlen),4,seqlen);
4484 /* fetch all octets in this sequence */
4485 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4488 * Now we may have the Repository ID from earlier, as well
4489 * as the object key sequence and lengh. So lets store them in
4490 * our objectkey hash and free buffers.
4492 * But only insert if user is not clicking and repo id not NULL.
4498 if(!pinfo->fd->flags.visited)
4499 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4504 * No pinfo, but store anyway if flag set. eg: IOR read from file
4508 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4512 /* Make a printable string */
4514 p_chars = make_printable_string( objkey, seqlen );
4517 proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
4518 "Object Key: %s", p_chars);
4526 * Now see if if its v1.1 or 1.2, as they can contain
4527 * extra sequence of IOP::TaggedComponents
4540 /* sequence of IOP::TaggedComponents */
4541 /* Ref Chap 13 in Corba Spec */
4543 /* get sequence length */
4544 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4547 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4548 *offset-sizeof(seqlen),4,seqlen);
4551 for (i=0; i< seqlen; i++) {
4553 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4555 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4556 *offset-sizeof(u_octet4),4,u_octet4);
4559 /* get component_data */
4560 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4562 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4563 *offset-sizeof(seqlen1),4,seqlen1);
4567 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4570 /* Make a printable string of data */
4572 p_chars = make_printable_string(buf, seqlen1);
4574 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4575 "component_data: %s", p_chars);
4589 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4597 * Service Contexts Begin
4606 void dissect_SID_BI_DIR_IIOP(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4607 MessageHeader *header, gchar *operation, guint32 boundary) {
4617 * Service Contexts End
4629 * typedef unsigned long ServiceID;
4631 * struct ServiceContext {
4632 * ServiceID context_id;
4633 * sequence <octet> context_data;
4635 * typedef sequence <ServiceContext> ServiceContextList;
4638 * Note: Spec says context_data is an encapsulation.
4645 void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *ptree, int *offset,
4646 gboolean stream_is_be, guint32 boundary) {
4648 guint32 seqlen; /* sequence length */
4649 guint32 seqlen_cd; /* sequence length, context_data */
4651 proto_tree *tree = NULL; /* ServiceContext tree */
4655 gchar *context_data;
4656 gchar *p_context_data;
4659 guint32 vscid; /* Vendor Service context id */
4662 /* create a subtree */
4665 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "ServiceContextList");
4666 tree = proto_item_add_subtree (tf, ett_giop_scl);
4669 /* Get sequence length (number of elements) */
4671 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4673 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4674 *offset-sizeof(seqlen),4,seqlen);
4677 /* return if zero length sequence */
4682 /* Loop for all ServiceContext's */
4684 for (i=0; i<seqlen; i++) {
4686 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4688 proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4689 *offset-sizeof(context_id),4,context_id);
4691 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4692 *offset-sizeof(context_id),4,context_id);
4696 vscid = context_id && 0xfffff000; /* vendor info, top 20 bits */
4697 scid = context_id && 0x00000fff; /* standard service info, lower 12 bits */
4700 #if CONTEXT_DATA_IS_ENCAPSULATED
4702 /* get sequence length, new endianness and boundary for encapsulation */
4704 seqlen_cd = get_CDR_encap_info(tvb, tree, offset,
4705 stream_is_be, boundary,
4706 &new_big_endianess, &new_boundary);
4710 /* get sequence length, and NO encapsulation */
4712 seqlen_cd = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4716 /* return if zero length sequence */
4722 * Now decode sequence according to vendor ServiceId, but I dont
4723 * have that yet, so just dump it as data.
4726 /* fetch all octets in this sequence */
4728 get_CDR_octet_seq(tvb, &context_data, offset, seqlen_cd);
4730 /* Make a printable string */
4732 p_context_data = make_printable_string( context_data, seqlen_cd );
4735 proto_tree_add_text (tree, tvb, *offset - seqlen_cd , seqlen_cd,
4736 "context_data: %s", p_context_data);
4739 g_free(context_data);
4740 g_free(p_context_data);
4745 return; /* for now, fix later */
4750 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
4753 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
4754 gboolean stream_is_big_endian,
4757 guint32 length; /* string length */
4758 guint32 minor_code_value;
4759 guint32 completion_status;
4761 gchar *buf; /* pointer to string buffer */
4763 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
4766 proto_tree_add_text(tree, tvb, *offset-4, 4,
4767 "Exception length: %u", length);
4769 proto_tree_add_text(tree, tvb, *offset - length, length,
4770 "Exception id: %s", buf );
4775 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4776 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4779 proto_tree_add_text(tree, tvb, *offset-8, 4,
4780 "Minor code value: %u", minor_code_value);
4781 proto_tree_add_text(tree, tvb, *offset-4, 4,
4782 "Completion Status: %u", completion_status);
4788 * Helper functions for dissecting TypeCodes
4790 * These functions decode the complex parameter lists
4791 * of TypeCodes as defined in the CORBA spec chapter 15.
4794 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4795 gboolean stream_is_big_endian, guint32 boundary) {
4797 guint32 new_boundary; /* new boundary for encapsulation */
4798 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4800 guint32 seqlen; /* sequence length */
4802 /* get sequence length, new endianness and boundary for encapsulation */
4803 seqlen = get_CDR_encap_info(tvb, tree, offset,
4804 stream_is_big_endian, boundary,
4805 &new_stream_is_big_endian, &new_boundary);
4807 /* get repository ID */
4808 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4812 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4813 hf_giop_typecode_name);
4818 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4819 gboolean stream_is_big_endian, guint32 boundary,
4820 MessageHeader * header ) {
4822 guint32 new_boundary; /* new boundary for encapsulation */
4823 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4825 guint32 count; /* parameter count (of tuples) */
4826 guint32 seqlen; /* sequence length */
4827 guint32 i; /* loop index */
4829 /* get sequence lengt,h new endianness and boundary for encapsulation */
4830 seqlen = get_CDR_encap_info(tvb, tree, offset,
4831 stream_is_big_endian, boundary,
4832 &new_stream_is_big_endian, &new_boundary);
4834 /* get repository ID */
4835 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4839 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4840 hf_giop_typecode_name);
4842 /* get count of tuples */
4843 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4845 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4846 *offset-sizeof(count),4,count);
4849 /* get all tuples */
4850 for (i=0; i< count; i++) {
4851 /* get member name */
4852 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4853 hf_giop_typecode_member_name);
4855 /* get member type */
4856 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4862 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4863 gboolean stream_is_big_endian, guint32 boundary,
4864 MessageHeader * header) {
4866 guint32 new_boundary; /* new boundary for encapsulation */
4867 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4869 guint32 TCKind; /* TypeCode */
4870 gint32 s_octet4; /* signed int32 */
4872 guint32 count; /* parameter count (of tuples) */
4873 guint32 seqlen; /* sequence length */
4874 guint32 i; /* loop index */
4876 /* get sequence legnth, new endianness and boundary for encapsulation */
4877 seqlen = get_CDR_encap_info(tvb, tree, offset,
4878 stream_is_big_endian, boundary,
4879 &new_stream_is_big_endian, &new_boundary);
4881 /* get repository ID */
4882 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4886 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4887 hf_giop_typecode_name);
4889 /* get discriminant type */
4890 TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4892 /* get default used */
4893 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
4895 proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
4896 *offset-sizeof(s_octet4),4,s_octet4);
4898 /* get count of tuples */
4899 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4901 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4902 *offset-sizeof(count),4,count);
4905 /* get all tuples */
4906 for (i=0; i< count; i++) {
4907 /* get label value, based on TCKind above */
4908 dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
4910 /* get member name */
4911 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4912 hf_giop_typecode_member_name);
4914 /* get member type */
4915 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4921 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4922 gboolean stream_is_big_endian, guint32 boundary) {
4924 guint32 new_boundary; /* new boundary for encapsulation */
4925 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4927 guint32 count; /* parameter count (of tuples) */
4928 guint32 seqlen; /* sequence length */
4929 guint32 i; /* loop index */
4931 /* get sequence length, new endianness and boundary for encapsulation */
4932 seqlen = get_CDR_encap_info(tvb, tree, offset,
4933 stream_is_big_endian, boundary,
4934 &new_stream_is_big_endian, &new_boundary);
4936 /* get repository ID */
4937 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4941 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4942 hf_giop_typecode_name);
4944 /* get count of tuples */
4945 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4947 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4948 *offset-sizeof(count),4,count);
4951 /* get all tuples */
4952 for (i=0; i< count; i++) {
4953 /* get member name */
4954 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4955 hf_giop_typecode_member_name);
4961 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4962 gboolean stream_is_big_endian, guint32 boundary,
4963 MessageHeader * header) {
4965 guint32 new_boundary; /* new boundary for encapsulation */
4966 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4968 guint32 u_octet4; /* unsigned int32 */
4970 guint32 seqlen; /* sequence length */
4972 /* get sequence length, new endianness and boundary for encapsulation */
4973 seqlen = get_CDR_encap_info(tvb, tree, offset,
4974 stream_is_big_endian, boundary,
4975 &new_stream_is_big_endian, &new_boundary);
4977 /* get element type */
4978 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4980 /* get max length */
4981 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4983 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
4984 *offset-sizeof(u_octet4),4,u_octet4);
4989 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4990 gboolean stream_is_big_endian, guint32 boundary,
4991 MessageHeader * header) {
4993 guint32 new_boundary; /* new boundary for encapsulation */
4994 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4996 guint32 u_octet4; /* unsigned int32 */
4998 guint32 seqlen; /* sequence length */
5000 /* get sequence length, new endianness and boundary for encapsulation */
5001 seqlen = get_CDR_encap_info(tvb, tree, offset,
5002 stream_is_big_endian, boundary,
5003 &new_stream_is_big_endian, &new_boundary);
5005 /* get element type */
5006 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5009 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5011 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5012 *offset-sizeof(u_octet4),4,u_octet4);
5017 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5018 gboolean stream_is_big_endian, guint32 boundary,
5019 MessageHeader * header) {
5021 guint32 new_boundary; /* new boundary for encapsulation */
5022 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5024 guint32 seqlen; /* sequence length */
5026 /* get sequence legnth, new endianness and boundary for encapsulation */
5027 seqlen = get_CDR_encap_info(tvb, tree, offset,
5028 stream_is_big_endian, boundary,
5029 &new_stream_is_big_endian, &new_boundary);
5031 /* get repository ID */
5032 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5036 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5037 hf_giop_typecode_name);
5039 /* get ??? (noname) TypeCode */
5040 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5045 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5046 gboolean stream_is_big_endian, guint32 boundary,
5047 MessageHeader * header) {
5049 guint32 new_boundary; /* new boundary for encapsulation */
5050 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5052 guint32 count; /* parameter count (of tuples) */
5053 guint32 seqlen; /* sequence length */
5054 guint32 i; /* loop index */
5056 /* get sequence length, new endianness and boundary for encapsulation */
5057 seqlen = get_CDR_encap_info(tvb, tree, offset,
5058 stream_is_big_endian, boundary,
5059 &new_stream_is_big_endian, &new_boundary);
5061 /* get repository ID */
5062 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5066 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5067 hf_giop_typecode_name);
5069 /* get count of tuples */
5070 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5072 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5073 *offset-sizeof(count),4,count);
5076 /* get all tuples */
5077 for (i=0; i< count; i++) {
5078 /* get member name */
5079 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5080 hf_giop_typecode_member_name);
5082 /* get member type */
5083 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5089 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5090 gboolean stream_is_big_endian, guint32 boundary,
5091 MessageHeader * header) {
5093 guint32 new_boundary; /* new boundary for encapsulation */
5094 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5096 gint16 s_octet2; /* signed int16 */
5098 guint32 count; /* parameter count (of tuples) */
5099 guint32 seqlen; /* sequence length */
5100 guint32 i; /* loop index */
5102 /* get sequence length, 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 ValueModifier */
5116 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5118 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5119 *offset-sizeof(s_octet2),2,s_octet2);
5122 /* get conrete base */
5123 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5125 /* get count of tuples */
5126 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5128 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5129 *offset-sizeof(count),4,count);
5132 /* get all tuples */
5133 for (i=0; i< count; i++) {
5134 /* get member name */
5135 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5136 hf_giop_typecode_member_name);
5138 /* get member type */
5139 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5141 /* get Visibility */
5142 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5144 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5145 *offset-sizeof(s_octet2),2,s_octet2);
5152 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5153 gboolean stream_is_big_endian, guint32 boundary,
5154 MessageHeader * header) {
5156 guint32 new_boundary; /* new boundary for encapsulation */
5157 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5159 guint32 seqlen; /* sequence length */
5161 /* get sequence length, new endianness and boundary for encapsulation */
5162 seqlen = get_CDR_encap_info(tvb, tree, offset,
5163 stream_is_big_endian, boundary,
5164 &new_stream_is_big_endian, &new_boundary);
5166 /* get repository ID */
5167 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5171 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5172 hf_giop_typecode_name);
5174 /* get ??? (noname) TypeCode */
5175 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5179 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5180 gboolean stream_is_big_endian, guint32 boundary) {
5182 guint32 new_boundary; /* new boundary for encapsulation */
5183 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5185 guint32 seqlen; /* sequence length */
5187 /* get sequence length, new endianness and boundary for encapsulation */
5188 seqlen = get_CDR_encap_info(tvb, tree, offset,
5189 stream_is_big_endian, boundary,
5190 &new_stream_is_big_endian, &new_boundary);
5192 /* get repository ID */
5193 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5197 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5198 hf_giop_typecode_name);
5203 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5204 gboolean stream_is_big_endian, guint32 boundary) {
5206 guint32 new_boundary; /* new boundary for encapsulation */
5207 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5209 guint32 seqlen; /* sequence length */
5211 /* get sequence length, new endianness and boundary for encapsulation */
5212 seqlen = get_CDR_encap_info(tvb, tree, offset,
5213 stream_is_big_endian, boundary,
5214 &new_stream_is_big_endian, &new_boundary);
5216 /* get repository ID */
5217 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5221 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5222 hf_giop_typecode_name);
5226 /* Typecode parameter lists are encoded as encapsulations and
5227 * this function gets the encapsulation information; see
5228 * CORBA spec chapter 15
5231 * Renamed to get_CDR_encap_info() for any encapsulation
5232 * we come across, useful helper function
5234 * Also, should return immediately if seqlen == 0.
5235 * ie: Forget about trying to grab endianess for
5236 * zero length sequence.
5238 * Caller must always check seqlen == 0, and not assume its value
5241 * Note: there seemed to be considerable confusion in corba
5242 * circles as to the correct interpretation of encapsulations,
5243 * and zero length sequences etc, but this is our best bet at the
5250 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5251 gboolean old_stream_is_big_endian, guint32 old_boundary,
5252 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5254 guint32 seqlen; /* sequence length */
5255 guint8 giop_endianess;
5257 /* Get sequence length of parameter list */
5258 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5260 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5261 *offset-sizeof(seqlen),4,seqlen);
5267 * seqlen == 0, implies no endianess and no data
5268 * so just return. Populate new_boundary_ptr and
5269 * new_stream_is_big_endian_ptr with current (old)
5270 * values, just to keep everyone happy. -- FS
5276 *new_boundary_ptr = old_boundary;
5277 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5283 /* Start of encapsulation of parameter list */
5284 *new_boundary_ptr = *offset; /* remember */
5285 giop_endianess = get_CDR_octet(tvb,offset);
5287 *new_stream_is_big_endian_ptr = ! giop_endianess;
5290 * Glib: typedef gint gboolean;
5291 * ie: It is not a guint8, so cannot use sizeof to correctly
5297 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5298 *offset-1,1,giop_endianess);
5308 * gets a TypeCode complex string parameter and
5309 * displays it in the relevant tree.
5312 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5313 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5315 guint32 u_octet4; /* unsigned int32 */
5316 gchar *buf; /* ptr to string buffer */
5319 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5322 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5323 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5325 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5329 g_free(buf); /* dont forget */
5334 * For a given data type, given by a TypeCode gets the associated data
5335 * and displays it in the relevant tree.
5338 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5339 gboolean stream_is_big_endian, guint32 boundary,
5340 MessageHeader * header, guint32 data_type ) {
5342 gboolean my_boolean; /* boolean */
5344 gint8 s_octet1; /* signed int8 */
5345 guint8 u_octet1; /* unsigned int8 */
5347 gint16 s_octet2; /* signed int16 */
5348 guint16 u_octet2; /* unsigned int16 */
5350 gint32 s_octet4; /* signed int32 */
5351 guint32 u_octet4; /* unsigned int32 */
5353 gdouble my_double; /* double */
5354 gfloat my_float; /* float */
5356 gchar *buf = NULL; /* ptr to string buffer */
5358 /* Grab the data according to data type */
5360 switch (data_type) {
5362 /* nothing to decode */
5365 /* nothing to decode */
5368 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5370 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5371 *offset-sizeof(s_octet2),2,s_octet2);
5375 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5377 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5378 *offset-sizeof(s_octet4),4,s_octet4);
5382 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5384 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5385 *offset-sizeof(u_octet2),2,u_octet2);
5389 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5391 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5392 *offset-sizeof(u_octet4),4,u_octet4);
5396 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5398 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5399 *offset-sizeof(my_float),4,my_float);
5403 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5405 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5406 *offset-sizeof(my_double),8,my_double);
5410 my_boolean = get_CDR_boolean(tvb,offset);
5412 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5413 *offset-1,1,my_boolean);
5417 u_octet1 = get_CDR_char(tvb,offset);
5419 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5420 *offset-sizeof(u_octet1),1,u_octet1);
5424 u_octet1 = get_CDR_octet(tvb,offset);
5426 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5427 *offset-sizeof(u_octet1),1,u_octet1);
5431 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5434 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5445 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5447 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5448 *offset-sizeof(u_octet4),4,u_octet4);
5452 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5454 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5455 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5457 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5458 *offset-u_octet4,u_octet4,buf);
5462 g_free(buf); /* dont forget */
5479 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5482 * XXX - can any of these throw an exception?
5483 * If so, we need to catch the exception and free "buf".
5485 if (s_octet1 < 0) { /* no size to add to tree */
5486 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5487 *offset+s_octet1,(-s_octet1),buf);
5489 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5490 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5491 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5492 *offset-s_octet1,s_octet1,buf);
5496 g_free(buf); /* dont forget */
5499 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5502 * XXX - can any of these throw an exception?
5503 * If so, we need to catch the exception and free "buf".
5505 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5506 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5507 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5508 *offset-u_octet4,u_octet4,buf);
5511 g_free(buf); /* dont forget */
5521 case tk_abstract_interface:
5524 g_warning("giop: Unknown typecode data type %u \n", data_type);