2 * Routines for CORBA GIOP/IIOP packet disassembly
5 * Laurent Deniel <laurent.deniel@free.fr>
6 * Craig Rodrigues <rodrigc@attbi.com>
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.76 2003/12/28 12:43:38 ulfl 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". "
291 #ifdef NEED_STRERROR_H
292 #include "strerror.h"
295 #include <epan/packet.h>
296 #include "packet-giop.h"
299 * Set to 1 for DEBUG output - TODO make this a runtime option
307 * ------------------------------------------------------------------------------------------+
308 * Private Helper function Declarations
309 * ------------------------------------------------------------------------------------------+
313 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
314 guint32 boundary, gboolean new_endianess, gchar *repobuf,
315 gboolean store_flag);
317 static void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *tree, int *offset,
318 gboolean stream_is_be, guint32 boundary);
320 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
321 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf);
323 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
324 guint32 boundary, gboolean stream_is_big_endian );
326 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
327 gboolean stream_is_big_endian,
330 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
331 gboolean stream_is_big_endian, guint32 boundary);
333 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
334 gboolean stream_is_big_endian, guint32 boundary,
335 MessageHeader * header);
337 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
338 gboolean stream_is_big_endian, guint32 boundary,
339 MessageHeader * header );
341 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
342 gboolean stream_is_big_endian, guint32 boundary);
344 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
345 gboolean stream_is_big_endian, guint32 boundary,
346 MessageHeader * header);
348 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
349 gboolean stream_is_big_endian, guint32 boundary,
350 MessageHeader * header);
352 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
353 gboolean stream_is_big_endian, guint32 boundary,
354 MessageHeader * header);
356 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
357 gboolean stream_is_big_endian, guint32 boundary,
358 MessageHeader * header);
360 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
361 gboolean stream_is_big_endian, guint32 boundary,
362 MessageHeader * header);
364 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
365 gboolean stream_is_big_endian, guint32 boundary,
366 MessageHeader * header);
368 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
369 gboolean stream_is_big_endian, guint32 boundary);
371 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
372 gboolean stream_is_big_endian, guint32 boundary);
375 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
376 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
378 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
379 gboolean stream_is_big_endian, guint32 boundary,
380 MessageHeader * header, guint32 data_type );
386 * ------------------------------------------------------------------------------------------+
387 * Data/Variables/Structs
388 * ------------------------------------------------------------------------------------------+
392 static int proto_giop = -1;
393 static int hf_giop_message_type = -1;
394 static int hf_giop_message_size = -1;
395 static int hf_giop_repoid = -1;
396 static int hf_giop_string_length = -1;
397 static int hf_giop_sequence_length = -1;
398 static int hf_giop_profile_id = -1;
399 static int hf_giop_type_id = -1;
400 static int hf_giop_iiop_v_maj = -1;
401 static int hf_giop_iiop_v_min = -1;
402 static int hf_giop_endianess = -1; /* esp encapsulations */
403 static int hf_giop_IOR_tag = -1;
404 static int hf_giop_IIOP_tag = -1;
406 static int hf_giop_TCKind = -1;
407 static int hf_giop_typecode_count = -1;
408 static int hf_giop_typecode_default_used = -1;
409 static int hf_giop_typecode_digits = -1;
410 static int hf_giop_typecode_length = -1;
411 static int hf_giop_typecode_max_length = -1;
412 static int hf_giop_typecode_member_name = -1;
413 static int hf_giop_typecode_name = -1;
414 static int hf_giop_typecode_scale = -1;
415 static int hf_giop_typecode_ValueModifier = -1;
416 static int hf_giop_typecode_Visibility = -1;
418 static int hf_giop_type_boolean = -1;
419 static int hf_giop_type_char = -1;
420 static int hf_giop_type_double = -1;
421 static int hf_giop_type_enum = -1;
422 static int hf_giop_type_float = -1;
423 static int hf_giop_type_long = -1;
424 static int hf_giop_type_octet = -1;
425 static int hf_giop_type_short = -1;
426 static int hf_giop_type_string = -1;
427 static int hf_giop_type_ulong = -1;
428 static int hf_giop_type_ushort = -1;
430 static int hf_giop_iiop_host = -1;
431 static int hf_giop_iiop_port = -1;
432 static int hf_giop_iop_vscid = -1;
433 static int hf_giop_iop_scid = -1;
439 static gint ett_giop = -1;
440 static gint ett_giop_reply = -1;
441 static gint ett_giop_request = -1;
442 static gint ett_giop_cancel_request = -1;
443 static gint ett_giop_locate_request = -1;
444 static gint ett_giop_locate_reply = -1;
445 static gint ett_giop_fragment = -1;
447 static gint ett_giop_scl = -1; /* ServiceContextList */
448 static gint ett_giop_scl_st1 = -1;
449 static gint ett_giop_ior = -1; /* IOR */
451 static dissector_handle_t data_handle;
454 static const value_string giop_endianess_vals[] = {
455 { 0x0, "Big Endian" },
456 { 0x1, "Little Endian" },
460 static const value_string sync_scope[] = {
461 { 0x0, "SYNC_NONE" },
462 { 0x1, "SYNC_WITH_TRANSPORT"},
463 { 0x2, "SYNC_WITH_SERVER"},
464 { 0x3, "SYNC_WITH_TARGET"},
470 static const value_string profile_id_vals[] = {
471 { 0x0, "TAG_INTERNET_IOP" },
472 { 0x1, "TAG_MULTIPLE_COMPONENTS"},
473 { 0x2, "TAG_SCCP_IOP"},
477 static const value_string giop_message_types[] = {
480 { 0x2, "CancelRequest"},
481 { 0x3, "LocateRequest"},
482 { 0x4, "LocateReply"},
483 { 0x5, "CloseConnection"},
484 { 0x6, "MessageError"},
489 static const value_string giop_locate_status_types[] = {
490 { 0x0, "Unknown Object" },
491 { 0x1, "Object Here"},
492 { 0x2, "Object Forward"},
493 { 0x3, "Object Forward Perm"},
494 { 0x4, "Loc System Exception"},
495 { 0x5, "Loc Needs Addressing Mode"},
499 static const value_string tckind_vals[] = {
512 { 12, "tk_TypeCode"},
513 { 13, "tk_Principal"},
519 { 19, "tk_sequence"},
523 { 23, "tk_longlong"},
524 { 24, "tk_ulonglong"},
525 { 25, "tk_longdouble"},
530 { 30, "tk_value_box"},
532 { 32, "tk_abstract_interface"},
537 * These values are taken from the CORBA 3.0.2 standard,
538 * section 13.7.1 "Standard Service Contexts".
540 static const guint32 max_service_context_id = 0x10;
541 static const value_string service_context_ids[] = {
542 { 0x00, "TransactionService" },
544 { 0x02, "ChainBypassCheck"},
545 { 0x03, "ChainBypassInfo"},
546 { 0x04, "LogicalThreadId"},
547 { 0x05, "BI_DIR_IIOP"},
548 { 0x06, "SendingContextRunTime"},
549 { 0x07, "INVOCATION_POLICIES"},
550 { 0x08, "FORWARDED_IDENTITY"},
551 { 0x09, "UnknownExceptionInfo"},
552 { 0x0a, "RTCorbaPriority"},
553 { 0x0b, "RTCorbaPriorityRange"},
554 { 0x0c, "FT_GROUP_VERSION"},
555 { 0x0d, "FT_REQUEST"},
556 { 0x0e, "ExceptionDetailMessage"},
557 { 0x0f, "SecurityAttributeService"},
558 { 0x10, "ActivityService"},
565 #define GIOP_MAGIC "GIOP"
568 * TAGS for IOR Profiles
570 * Chapter 13 Corba 2.4.2
574 #define IOP_TAG_INTERNET_IOP 0
575 #define IOP_TAG_MULTIPLE_COMPONENTS 1
578 /* Max Supported versions */
580 static const guint GIOP_MAJOR = 1;
581 static const guint GIOP_MINOR = 2;
584 static const int KeyAddr = 0;
585 static const int ProfileAddr = 1;
586 static const int ReferenceAddr = 2;
590 static const value_string reply_status_types[] = {
591 { NO_EXCEPTION, "No Exception" } ,
592 { USER_EXCEPTION, "User Exception" } ,
593 { SYSTEM_EXCEPTION, "System Exception" } ,
594 { LOCATION_FORWARD, "Location Forward" } ,
595 { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
596 { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
602 typedef enum LocateStatusType
607 OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
608 LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
609 LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
613 typedef struct LocateReplyHeader
616 guint32 locate_status;
622 * DATA - complete_request_list
625 static GList *giop_complete_request_list;
627 struct comp_req_list_entry {
628 guint32 fn; /* frame number */
629 gchar * operation; /* echo echoString */
630 giop_sub_handle_t *subh; /* handle to sub dissector */
631 guint32 reqid; /* request id */
632 gchar * repoid; /* repository ID */
635 typedef struct comp_req_list_entry comp_req_list_entry_t;
639 * DATA - complete_reply_hash
641 * Maps reply FN to request MFN
644 static int complete_reply_hash_count = 1000; /* storage size for our permanent data */
645 /* ie: 1000 entries -- needs tweaking -- FS */
647 struct complete_reply_hash_key {
648 guint32 fn; /* reply frame number */
651 struct complete_reply_hash_val {
652 guint32 mfn; /* matching frame number (request) */
655 GHashTable *giop_complete_reply_hash = NULL; /* hash */
656 GMemChunk *giop_complete_reply_keys = NULL; /* key storage */
657 GMemChunk *giop_complete_reply_vals = NULL; /* val storage */
661 * DATA - Module Hash stuff to store data from register_giop_user_module
663 * ie: module (or interface ?) name, and ptr to sub_dissector handle
665 * With this knowledge, we can call a sub dissector directly,
668 * objkey -> repoid -> sub_dissector via registered module/interface
673 static int giop_module_init_count = 100; /* storage size for our permanent data */
674 /* ie: 100 entries -- needs tweaking -- FS */
676 struct giop_module_key {
677 gchar *module; /* module (interface?) name */
680 struct giop_module_val {
681 giop_sub_handle_t *subh; /* handle to sub dissector */
684 GHashTable *giop_module_hash = NULL; /* hash */
685 GMemChunk *giop_module_keys = NULL; /* key storage */
686 GMemChunk *giop_module_vals = NULL; /* val storage */
690 * DATA - GSList to store list of function (dissector) pointers.
691 * for heuristic dissection.
695 static GSList *giop_sub_list = NULL;
698 * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
699 * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
701 * With this knowledge, we can call a sub dissector directly later
704 * objkey -> repoid -> sub_dissector via registered module/interface
706 * rather than heuristic calls that do not provide operation context.
707 * (unless we pass the RepoID for a given objkey -- hmmm)
712 * Interesting operation list, add more if you want to save
716 static const char giop_op_resolve[] = "resolve";
717 static const char giop_op_bind_new_context[] = "bind_new_context";
718 static const char giop_op_bind[] = "bind";
721 * Enums for interesting local operations, that we may need to monitor
722 * with their subsequent replies
727 request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
728 request_bind_new_context_op_val, /* bind_new_context */
729 request_bind_op_val, /* bind */
730 request_get_INIT_op_val /* finding Nameserver */
736 * hash for mapping object keys onto object namespaces, so
737 * I can call the correct dissector.
743 * Where did I get the IOR from.
747 req_res = 0, /* REQUEST (resolve) */
748 file /* stringified IOR' in a file */
752 typedef enum ior_src ior_src_t;
757 * Enums for my lists and hash's
760 enum collection_data {
761 cd_heuristic_users = 0,
764 cd_complete_request_list,
765 cd_complete_reply_hash
768 typedef enum collection_data collection_data_t;
772 static int giop_objkey_init_count = 100; /* storage size for our permanent data */
773 /* ie: 100 entries -- needs tweaking -- FS */
775 struct giop_object_key {
776 guint8 *objkey; /* ptr to object key */
777 guint32 objkey_len; /* length */
780 struct giop_object_val {
781 guint8 *repo_id; /* ptr to Repository ID string */
782 ior_src_t src; /* where did Iget this IOR from */
785 GHashTable *giop_objkey_hash = NULL; /* hash */
786 GMemChunk *giop_objkey_keys = NULL; /* key storage */
787 GMemChunk *giop_objkey_vals = NULL; /* val storage */
792 * ------------------------------------------------------------------------------------------+
793 * Private helper functions
794 * ------------------------------------------------------------------------------------------+
800 * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
803 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
804 GList * newlist_start;
805 comp_req_list_entry_t * entry = NULL;
808 entry = g_malloc(sizeof(comp_req_list_entry_t));
809 opn = g_strdup(op); /* duplicate operation for storage */
812 entry->reqid = reqid;
814 entry->operation = opn;
815 entry->repoid = NULL; /* dont have yet */
817 newlist_start = g_list_append (list, entry); /* append */
819 return newlist_start;
824 * Used to find an entry with matching Frame Number FN
825 * in the complete_request_list list.
828 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
830 GList * element; /* entry in list */
831 comp_req_list_entry_t * entry_ptr = NULL;
833 element = g_list_last(giop_complete_request_list); /* start from last */
835 while(element) { /* valid list entry */
836 entry_ptr = element->data; /* grab data pointer */
837 if (entry_ptr->fn == fn) { /* similar FN */
840 element = g_list_previous(element); /* try next previous */
843 return NULL; /* no match so return NULL */
848 * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
850 * Call this when you know a FN and matching giop_sub_handle_t and repoid
852 * This is done in say, try_explicit_dissector for example.
856 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
858 comp_req_list_entry_t * entry = NULL;
859 entry = find_fn_in_list(fn); /* grab FN data entry */
863 entry->repoid = g_strdup(repoid); /* copy and store */
871 /* giop_complete_reply_hash "EQUAL" Functions */
873 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
874 const struct complete_reply_hash_key *mk1 = (const struct complete_reply_hash_key *)v;
875 const struct complete_reply_hash_key *mk2 = (const struct complete_reply_hash_key *)w;
877 if (mk1->fn == mk2->fn) {
881 return 0; /* found differences */
884 /* giop_complete_reply_hash "HASH" Functions */
886 static guint32 complete_reply_hash_fn(gconstpointer v) {
887 guint32 val; /* init hash value */
888 const struct complete_reply_hash_key *key = (const struct complete_reply_hash_key *)v;
890 val = key->fn; /* simple and unique */
897 * Insert the FN and MFN together in our complete_reply_hash.
900 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
902 struct complete_reply_hash_key key, *new_key;
903 struct complete_reply_hash_val *val = NULL;
907 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
910 return; /* FN collision */
913 new_key = g_mem_chunk_alloc(giop_complete_reply_keys);
914 new_key->fn = fn; /* save FN */
916 val = g_mem_chunk_alloc(giop_complete_reply_vals);
917 val->mfn = mfn; /* and MFN */
919 g_hash_table_insert(giop_complete_reply_hash, new_key, val);
924 * Find the MFN values from a given FN key.
925 * Assumes the complete_reply_hash is already populated.
928 static guint32 get_mfn_from_fn(guint32 fn) {
930 struct complete_reply_hash_key key;
931 struct complete_reply_hash_val *val = NULL;
932 guint32 mfn = fn; /* save */
935 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
938 mfn = val->mfn; /* grab it */
941 return mfn; /* mfn or fn if not found */
946 * Attempt to find the MFN for this FN, and return it.
947 * Return MFN if found, or just FN if not. This is
948 * only used when we are building
951 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
953 GList * element; /* last entry in list */
954 comp_req_list_entry_t * entry_ptr = NULL;
956 /* Need Some pretty snappy code */
958 /* Loop back from current end of complete_request_list looking for */
959 /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
962 * As this routine is only called during initial pass of data,
963 * and NOT when a user clicks, it is ok to start from Current
964 * end of complete_request_list when searching for a match.
965 * As that list is bing populated in the same order as FN's
968 * Also, can make check for same reqid more detailed, but I start
969 * with reqid. Could add say port or address checks etc later ??
973 element = g_list_last(giop_complete_request_list); /* get last */
975 while(element) { /* valid list entry */
976 entry_ptr = element->data; /* grab data pointer */
977 if (entry_ptr->reqid == reqid) { /* similar reqid */
978 return entry_ptr->fn; /* return MFN */
980 element = g_list_previous(element); /* try next previous */
983 return fn; /* no match so return FN */
987 /* Module Hash "EQUAL" Functions */
989 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
990 const struct giop_module_key *mk1 = (const struct giop_module_key *)v;
991 const struct giop_module_key *mk2 = (const struct giop_module_key *)w;
993 if (strcmp(mk1->module, mk2->module) == 0) {
997 return 0; /* found differences */
1000 /* Module Hash "HASH" Functions */
1002 static guint32 giop_hash_module_hash(gconstpointer v) {
1005 guint32 val = 0; /* init hash value */
1007 const struct giop_module_key *key = (const struct giop_module_key *)v;
1010 * Hmm, try this simple hashing scheme for now.
1011 * ie: Simple summation, FIX later -- FS
1016 len = strlen(key->module);
1018 for (i=0; i<len; i++) {
1019 val += (guint8) key->module[i];
1028 * ------------------------------------------------------------------------------------------+
1029 * Public Utility functions
1030 * ------------------------------------------------------------------------------------------+
1037 * Routine to allow giop users to register their sub dissector function, name, and
1038 * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1039 * value returned from their proto_register_protocol(), so we can enable/disbale it
1040 * through the GUI (edit protocols).
1042 * This is used by try_explicit_giop_dissector() to find the
1043 * correct sub-dissector.
1047 void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
1049 struct giop_module_key module_key, *new_module_key;
1050 struct giop_module_val *module_val = NULL;
1052 module_key.module = module; /* module name */
1054 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1057 return; /* module name collision */
1060 /* So, passed module name should NOT exist in hash at this point.*/
1063 printf("giop:register_module: Adding Module %s to module hash \n", module);
1064 printf("giop:register_module: Module sub dissector name is %s \n", name);
1067 new_module_key = g_mem_chunk_alloc(giop_module_keys);
1068 new_module_key->module = module; /* save Module or interface name from IDL */
1070 module_val = g_mem_chunk_alloc(giop_module_vals);
1072 module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
1074 module_val->subh->sub_name = name; /* save dissector name */
1075 module_val->subh->sub_fn = sub; /* save subdissector*/
1076 module_val->subh->sub_proto = find_protocol_by_id(sub_proto); /* save protocol_t for subdissector's protocol */
1078 g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1085 /* Object Key Hash "EQUAL" Functions */
1087 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1088 const struct giop_object_key *v1 = (const struct giop_object_key *)v;
1089 const struct giop_object_key *v2 = (const struct giop_object_key *)w;
1091 if (v1->objkey_len != v2->objkey_len)
1092 return 0; /* no match because different length */
1094 /* Now do a byte comaprison */
1096 if (memcmp(v1->objkey,v2->objkey, v1->objkey_len) == 0) {
1097 return 1; /* compares ok */
1101 printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1104 return 0; /* found differences */
1107 /* Object Key Hash "HASH" Functions */
1109 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1110 const struct giop_object_key *key = (const struct giop_object_key *)v;
1113 guint32 val = 0; /* init hash value */
1117 * Hmm, try this simple hashing scheme for now.
1118 * ie: Simple summation
1124 printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1127 for (i=0; i< key->objkey_len; i++) {
1128 val += (guint8) key->objkey[i];
1136 * Routine to take an object key octet sequence, and length, and ptr to
1137 * a (null terminated )repository ID string, and store them in the obect key hash.
1139 * Blindly Inserts even if it does exist, See TODO at top for reason.
1142 static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
1144 struct giop_object_key objkey_key, *new_objkey_key;
1145 struct giop_object_val *objkey_val = NULL;
1147 objkey_key.objkey_len = len; /* length */
1148 objkey_key.objkey = obj; /* object key octet sequence */
1150 /* Look it up to see if it exists */
1152 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1154 /* CHANGED -- Same reqid, so abandon old entry */
1157 g_hash_table_remove(hash, &objkey_key);
1160 /* So, passed key should NOT exist in hash at this point.*/
1162 new_objkey_key = g_mem_chunk_alloc(giop_objkey_keys);
1163 new_objkey_key->objkey_len = len; /* save it */
1164 new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */
1166 objkey_val = g_mem_chunk_alloc(giop_objkey_vals);
1167 objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
1168 objkey_val->src = src; /* where IOR came from */
1172 printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
1173 objkey_val->repo_id, new_objkey_key->objkey_len);
1176 g_hash_table_insert(hash, new_objkey_key, objkey_val);
1183 * convert an ascii char representing a hex value,
1184 * to a numeric value.
1186 * returns value, or -1 if problem.
1190 static gint8 hex_char_to_val(guchar c){
1197 retval = c - 48; /* convert digit */
1201 c = toupper(c); /* convert to uppercase */
1202 if (c >= 'A' && c <= 'F') {
1213 * Convert from stringified IOR of the kind IOR:af4f7e459f....
1214 * to an IOR octet sequence.
1216 * User must free buffer.
1218 * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1219 * grab repoid etc for our objkey hash.
1223 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1226 gint8 tmpval; /* complete value */
1229 *out = g_new0(guint8, in_len); /* allocate buffer */
1235 /* skip past IOR: and convert character pairs to guint8 */
1237 for (i=4; i<in_len-1; i+=2) {
1238 if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1240 if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1241 g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1245 if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1246 g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1249 tmpval = tmpval_msb << 4;
1250 tmpval += tmpval_lsb;
1251 (*out)[(i-4)/2] = (guint8) tmpval;
1261 return (i-4)/2; /* length */
1268 * Simple "get a line" routine, copied from somewhere :)
1272 static int giop_getline(FILE *fp, gchar *line, int maxlen) {
1274 if (fgets(line,maxlen,fp) == NULL)
1277 return strlen(line);
1283 * Read a list of stringified IOR's from a named file, convert to IOR's
1284 * and store in object key hash
1287 static void read_IOR_strings_from_file(gchar *name, int max_iorlen) {
1288 guchar *buf; /* NOTE reused for every line */
1290 int ior_val_len; /* length after unstringifying. */
1292 guint8 *out; /* ptr to unstringified IOR */
1293 tvbuff_t *tvb; /* temp tvbuff for dissectin IORs */
1294 guint32 my_offset = 0;
1295 gboolean stream_is_big_endian;
1298 fp = fopen(name,"r"); /* open read only */
1301 if (errno == EACCES)
1302 fprintf(stderr, "Error opening file IOR.txt for reading: %s\n",strerror(errno));
1306 buf = g_malloc0(max_iorlen+1); /* input buf */
1308 while ((len = giop_getline(fp,buf,max_iorlen+1)) > 0) {
1309 my_offset = 0; /* reset for every IOR read */
1311 ior_val_len = string_to_IOR(buf,len,&out); /* convert */
1315 /* Combination of tvb_new() and tvb_set_real_data().
1316 Can throw ReportedBoundsError.
1318 XXX - can it throw an exception in this case? If so, we
1319 need to catch it and clean up, but we really shouldn't allow
1320 it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
1323 tvb = tvb_new_real_data(out, ior_val_len, ior_val_len);
1325 stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1326 decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1336 fclose(fp); /* be nice */
1344 * Init routine, setup our request hash stuff, or delete old ref's
1346 * Cannot setup the module hash here as my init() may not be called before
1347 * users start registering. So I will move the module_hash stuff to
1348 * proto_register_giop, as is done with packet-rpc
1352 * Also, setup our objectkey/repoid hash here.
1356 static void giop_init(void) {
1360 * Create objkey/repoid hash, use my "equal" and "hash" functions.
1364 if (giop_objkey_hash)
1365 g_hash_table_destroy(giop_objkey_hash);
1366 if (giop_objkey_keys)
1367 g_mem_chunk_destroy(giop_objkey_keys);
1368 if (giop_objkey_vals)
1369 g_mem_chunk_destroy(giop_objkey_vals);
1373 * Create hash, use my "equal" and "hash" functions.
1377 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1379 giop_objkey_keys = g_mem_chunk_new("giop_objkey_keys",
1380 sizeof(struct giop_object_key),
1381 giop_objkey_init_count * sizeof(struct giop_object_key),
1384 giop_objkey_vals = g_mem_chunk_new("giop_objkey_vals",
1385 sizeof(struct giop_object_val),
1386 giop_objkey_init_count * sizeof(struct giop_object_val),
1391 * Create complete_reply_hash, use my "equal" and "hash" functions.
1395 if (giop_complete_reply_hash)
1396 g_hash_table_destroy(giop_complete_reply_hash);
1397 if (giop_complete_reply_keys)
1398 g_mem_chunk_destroy(giop_complete_reply_keys);
1399 if (giop_complete_reply_vals)
1400 g_mem_chunk_destroy(giop_complete_reply_vals);
1404 * Create hash, use my "equal" and "hash" functions.
1408 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1410 giop_complete_reply_keys = g_mem_chunk_new("giop_complete_reply_keys",
1411 sizeof(struct complete_reply_hash_key),
1412 complete_reply_hash_count * sizeof(struct complete_reply_hash_key),
1415 giop_complete_reply_vals = g_mem_chunk_new("giop_complete_reply_vals",
1416 sizeof(struct complete_reply_hash_val),
1417 complete_reply_hash_count * sizeof(struct complete_reply_hash_val),
1422 read_IOR_strings_from_file("IOR.txt", 600); /* testing */
1429 * Insert an entry in the GIOP Heuristic User table.
1431 * Uses giop_sub_handle_t to wrap giop user info.
1435 void register_giop_user(giop_sub_dissector_t *sub, gchar *name, int sub_proto) {
1437 giop_sub_handle_t *subh;
1439 subh = g_malloc(sizeof (giop_sub_handle_t));
1441 subh->sub_name = name;
1443 subh->sub_proto = find_protocol_by_id(sub_proto); /* protocol_t for sub dissectors's proto_register_protocol() */
1445 giop_sub_list = g_slist_append (giop_sub_list, subh);
1451 * Lookup an object key in our object key hash, and return the corresponding
1456 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1458 struct giop_object_key objkey_key;
1459 struct giop_object_val *objkey_val = NULL;
1461 objkey_key.objkey_len = len; /* length */
1462 objkey_key.objkey = obj; /* object key octet sequence */
1464 /* Look it up to see if it exists */
1466 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1470 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1472 return objkey_val->repo_id; /* found */
1476 printf("FAILED Lookup of object key \n" );
1479 return NULL; /* not found */
1485 * Extract top level module/interface from repoid
1487 * eg from - "IDL:Echo/interface1:1.0"
1490 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1491 * get linux.org/Penguin/Teeth
1494 * User must free returned ptr after use.
1496 * TODO -- generalize for other Repoid encodings
1499 static gchar * get_modname_from_repoid(gchar *repoid) {
1501 gchar *modname = NULL;
1502 gchar *saved_repoid = NULL;
1504 guint8 stop_mod = 0; /* Index of last character of modname in Repoid */
1505 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1508 saved_repoid = g_strdup(repoid); /* make a copy */
1510 /* Must start with IDL: , otherwise I get confused */
1512 if (g_strncasecmp("IDL:",repoid,4))
1515 /* Looks like a RepoID to me, so get Module or interface name */
1517 /* TODO -- put some code here to get Module name */
1519 for(i=4; c != '\0'; i++) {
1521 stop_mod = i; /* save */
1522 if (c == ':' ) /* delimiters */
1527 /* Now create a new string based on start and stop and \0 */
1529 modname = g_strndup(repoid+4, stop_mod - start_mod);
1544 * Display a "module" hash entry
1547 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1549 struct giop_module_val *mv = (struct giop_module_val *) val;
1550 struct giop_module_key *mk = (struct giop_module_key *) key;
1552 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1559 * Display a "complete_reply " hash entry
1562 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1564 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1565 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1567 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1575 * Display an "objkey" hash entry
1578 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1580 struct giop_object_val *mv = (struct giop_object_val *) val;
1581 struct giop_object_key *mk = (struct giop_object_key *) key;
1584 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1586 for (i=0; i<mk->objkey_len; i++) {
1587 printf("%.2x ", mk->objkey[i]);
1591 * If read from file, mark it as such..
1595 printf(", Repo ID = %s \n", mv->repo_id);
1598 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1606 * Display all giop_sub_list (GSList) entries
1609 static void display_heuristic_user_list() {
1612 giop_sub_handle_t *subh; /* handle */
1614 /* Get length of list */
1615 len = g_slist_length(giop_sub_list); /* find length */
1620 for (i=0; i<len; i++) {
1621 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1622 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1628 * Display all complete_request_list (GList) entries
1631 static void display_complete_request_list() {
1634 comp_req_list_entry_t *entry;
1636 /* Get length of list */
1637 len = g_list_length(giop_complete_request_list); /* find length */
1642 for (i=0; i<len; i++) {
1643 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1644 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1645 entry->reqid,entry->operation, entry->repoid);
1653 /* Dump Hash/List contents
1655 * collection_type specifies the list or hash to dump
1659 static void giop_dump_collection(collection_data_t collection_type) {
1661 switch(collection_type) {
1662 case cd_heuristic_users:
1663 printf("+----------------------------------------------+ \n");
1664 printf("+-------------- Heuristic User (Begin) --------+ \n");
1665 printf("+----------------------------------------------+ \n");
1667 display_heuristic_user_list();
1669 printf("+----------------------------------------------+ \n");
1670 printf("+-------------- Heuristic User (End) ----------+ \n");
1671 printf("+----------------------------------------------+ \n");
1675 case cd_complete_request_list:
1676 printf("+----------------------------------------------+ \n");
1677 printf("+------------- Complete Request List (Begin) --+ \n");
1678 printf("+----------------------------------------------+ \n");
1680 display_complete_request_list();
1682 printf("+----------------------------------------------+ \n");
1683 printf("+------------ Complete Request List (End) -----+ \n");
1684 printf("+----------------------------------------------+ \n");
1688 case cd_module_hash:
1689 printf("+----------------------------------------------+ \n");
1690 printf("+-------------- Module (Begin) ----------------+ \n");
1691 printf("+----------------------------------------------+ \n");
1693 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1695 printf("+----------------------------------------------+ \n");
1696 printf("+-------------- Module ( End) -----------------+ \n");
1697 printf("+----------------------------------------------+ \n\n");
1701 case cd_objkey_hash:
1702 printf("+----------------------------------------------+ \n");
1703 printf("+-------------- Objkey (Begin) ----------------+ \n");
1704 printf("+----------------------------------------------+ \n");
1706 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1708 printf("+----------------------------------------------+ \n");
1709 printf("+-------------- Objkey (End) ------------------+ \n");
1710 printf("+----------------------------------------------+ \n\n");
1714 case cd_complete_reply_hash:
1715 printf("+----------------------------------------------+ \n");
1716 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1717 printf("+----------------------------------------------+ \n");
1719 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1721 printf("+----------------------------------------------+ \n");
1722 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1723 printf("+----------------------------------------------+ \n");
1729 printf("giop: giop_dump_collection: Unknown type \n");
1740 * Loop through all subdissectors, and call them until someone
1741 * answers (returns TRUE). This function then returns TRUE, otherwise
1744 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1747 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1748 MessageHeader *header, gchar *operation ) {
1751 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1752 giop_sub_handle_t *subh = NULL;
1753 const char *saved_proto;
1755 len = g_slist_length(giop_sub_list); /* find length */
1760 saved_proto = pinfo->current_proto;
1761 for (i=0; i<len; i++) {
1762 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1764 if (proto_is_protocol_enabled(subh->sub_proto)) {
1765 pinfo->current_proto =
1766 proto_get_protocol_short_name(subh->sub_proto);
1767 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1769 pinfo->current_proto = saved_proto;
1770 return TRUE; /* found one, lets return */
1772 } /* protocol_is_enabled */
1775 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1776 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
1778 pinfo->current_proto = saved_proto;
1779 return res; /* result */
1785 * Find the matching repoid in the module hash and call
1786 * the dissector function if offset exists.
1789 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1790 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1796 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1797 MessageHeader *header, gchar *operation, gchar *repoid ) {
1799 giop_sub_handle_t *subdiss = NULL; /* handle */
1800 gboolean res = FALSE;
1801 gchar *modname = NULL;
1802 struct giop_module_key module_key;
1803 struct giop_module_val *module_val = NULL;
1804 const char *saved_proto;
1808 * Get top level module/interface from complete repoid
1811 modname = get_modname_from_repoid(repoid);
1812 if (modname == NULL) {
1813 return res; /* unknown module name */
1817 /* Search for Module or interface name */
1819 module_key.module = modname; /* module name */
1820 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1822 if (module_val == NULL) {
1823 return res; /* module not registered */
1826 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1829 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1830 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1831 /* but only if user not clicking */
1833 if (!pinfo->fd->flags.visited)
1834 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1837 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1839 if (tvb_offset_exists(tvb, *offset)) {
1841 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1844 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1846 saved_proto = pinfo->current_proto;
1847 pinfo->current_proto =
1848 proto_get_protocol_short_name(subdiss->sub_proto);
1849 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1850 pinfo->current_proto = saved_proto;
1852 } /* protocol_is_enabled */
1853 } /* offset exists */
1856 return res; /* return result */
1861 /* Take in an array of char and create a new string.
1862 * Replace non-printable characters with periods.
1864 * The array may contain \0's so dont use strdup
1865 * The string is \0 terminated, and thus longer than
1866 * the initial sequence.
1867 * Caller must free the new string.
1870 static gchar * make_printable_string (gchar *in, guint32 len) {
1872 gchar *print_string = NULL;
1874 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1875 memcpy(print_string, in, len); /* and make a copy of input data */
1877 for(i=0; i < len; i++) {
1878 if( !isprint( (unsigned char)print_string[i] ) )
1879 print_string[i] = '.';
1882 return print_string; /* return ptr */
1885 /* Determine the byte order from the GIOP MessageHeader */
1887 gboolean is_big_endian (MessageHeader * header) {
1888 gboolean big_endian = FALSE;
1890 switch (header->GIOP_version.minor) {
1893 if (header->flags & 0x01)
1913 * Calculate new offset, based on the current offset, and user supplied
1914 * "offset delta" value, and the alignment requirement.
1918 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1919 * aligned on 8 byte boundaries.
1922 static void set_new_alignment(int *offset, int delta, int alignment) {
1924 while( ( (*offset + delta) % alignment) != 0)
1933 * ------------------------------------------------------------------------------------------+
1934 * Public get_CDR_xxx functions.
1935 * ------------------------------------------------------------------------------------------+
1941 * Gets data of type any. This is encoded as a TypeCode
1942 * followed by the encoded value.
1945 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1946 gboolean stream_is_big_endian, int boundary,
1947 MessageHeader * header ) {
1949 guint32 TCKind; /* TypeCode */
1951 /* get TypeCode of any */
1952 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1954 /* dissect data of type TCKind */
1955 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1959 /* Copy a 1 octet sequence from the tvbuff
1960 * which represents a boolean value, and convert
1961 * it to a boolean value.
1962 * Offset is then incremented by 1, to indicate the 1 octet which
1963 * has been processed.
1966 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1969 val = tvb_get_guint8(tvb, *offset); /* easy */
1974 /* Copy a 1 octet sequence from the tvbuff
1975 * which represents a char, and convert
1976 * it to an char value.
1977 * offset is then incremented by 1, to indicate the 1 octet which
1978 * has been processed.
1981 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1984 val = tvb_get_guint8(tvb, *offset); /* easy */
1992 * Floating Point Data Type double IEEE 754-1985
1994 * Copy an 8 octet sequence from the tvbuff
1995 * which represents a double value, and convert
1996 * it to a double value, taking into account byte order.
1997 * offset is first incremented so that it falls on a proper alignment
1998 * boundary for double values.
1999 * offset is then incremented by 8, to indicate the 8 octets which
2000 * have been processed.
2003 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2007 /* double values must be aligned on a 8 byte boundary */
2009 while( ( (*offset + boundary) % 8) != 0)
2012 val = (stream_is_big_endian) ? tvb_get_ntohieee_double (tvb, *offset) :
2013 tvb_get_letohieee_double (tvb, *offset);
2021 /* Copy a 4 octet sequence from the tvbuff
2022 * which represents an enum value, and convert
2023 * it to an enum value, taking into account byte order.
2024 * offset is first incremented so that it falls on a proper alignment
2025 * boundary for an enum (4)
2026 * offset is then incremented by 4, to indicate the 4 octets which
2027 * have been processed.
2029 * Enum values are encoded as unsigned long.
2033 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2035 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2041 * Copy an octet sequence from the tvbuff
2042 * which represents a Fixed point decimal type, and create a string representing
2043 * a Fixed point decimal type. There are no alignment restrictions.
2044 * Size and scale of fixed decimal type is determined by IDL.
2046 * digits - IDL specified number of "digits" for this fixed type
2047 * scale - IDL specified "scale" for this fixed type
2050 * eg: typedef fixed <5,2> fixed_t;
2051 * could represent numbers like 123.45, 789.12,
2054 * As the fixed type could be any size, I will not try to fit it into our
2055 * simple types like gdouble or glong etc. I will just create a string buffer holding
2056 * a representation (after scale is applied), and with a decimal point or zero padding
2057 * inserted at the right place if necessary. The string is null terminated
2059 * so string may look like
2062 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2064 * According to spec, digits <= 31
2065 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2068 * User must remember to free the buffer
2073 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2075 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2076 guint32 i ; /* loop */
2077 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2078 /* this does not include sign, decimal point and \0 */
2079 guint32 sindex = 0; /* string index */
2080 gchar *tmpbuf; /* temp buff, holds string without scaling */
2081 guint8 tval; /* temp val storage */
2084 * how many bytes to hold digits and scale (if scale <0)
2086 * eg: fixed <5,2> = 5 digits
2087 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2091 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2095 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2097 slen = digits; /* digits */
2101 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2104 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2107 * Register a cleanup function in case on of our tvbuff accesses
2108 * throws an exception. We need to clean up tmpbuf.
2110 CLEANUP_PUSH(g_free, tmpbuf);
2112 /* If even , grab 1st dig */
2114 if (!(digits & 0x01)) {
2115 tval = get_CDR_octet(tvb,offset);
2117 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2119 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2124 * Loop, but stop BEFORE we hit last digit and sign
2125 * if digits = 1 or 2, then this part is skipped
2129 for(i=0; i< ((digits-1)/2 ); i++) {
2130 tval = get_CDR_octet(tvb,offset);
2132 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2135 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2137 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2144 printf("giop:get_CDR_fixed(): before last digit \n");
2148 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2150 tval = get_CDR_octet(tvb,offset);
2152 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2154 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2157 sign = tval & 0x0f; /* get sign */
2159 /* So now, we have all digits in an array, and the sign byte
2160 * so lets generate a printable string, taking into account the scale
2164 sindex = 0; /* reset */
2165 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2166 * \0 -- TODO check slen is reasonable first */
2168 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2173 (*seq)[sindex] = '+'; /* put sign in first string position */
2176 (*seq)[sindex] = '-';
2179 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2180 (*seq)[sindex] = '*'; /* flag as sign unkown */
2186 /* Add decimal point or padding 0's, depending if scale is positive or
2187 * negative, respectively
2191 for (i=0; i<digits-scale; i++) {
2192 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2196 (*seq)[sindex] = '.'; /* decimal point */
2199 for (i=digits-scale; i<digits; i++) {
2200 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2204 (*seq)[sindex] = '\0'; /* string terminator */
2208 /* negative scale, dump digits and pad out with 0's */
2210 for (i=0; i<digits-scale; i++) {
2212 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2214 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2219 (*seq)[sindex] = '\0'; /* string terminator */
2224 * We're done with tmpbuf, so we can call the cleanup handler to free
2225 * it, and then pop the cleanup handler.
2227 CLEANUP_CALL_AND_POP;
2230 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2240 * Floating Point Data Type float IEEE 754-1985
2242 * Copy an 4 octet sequence from the tvbuff
2243 * which represents a float value, and convert
2244 * it to a float value, taking into account byte order.
2245 * offset is first incremented so that it falls on a proper alignment
2246 * boundary for float values.
2247 * offset is then incremented by 4, to indicate the 4 octets which
2248 * have been processed.
2251 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2255 /* float values must be aligned on a 4 byte boundary */
2257 while( ( (*offset + boundary) % 4) != 0)
2260 val = (stream_is_big_endian) ? tvb_get_ntohieee_float (tvb, *offset) :
2261 tvb_get_letohieee_float (tvb, *offset);
2270 * Decode an Interface type, and display it on the tree.
2273 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2274 gboolean stream_is_big_endian, int boundary) {
2277 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2283 /* Copy a 4 octet sequence from the tvbuff
2284 * which represents a signed long value, and convert
2285 * it to an signed long vaule, taking into account byte order.
2286 * offset is first incremented so that it falls on a proper alignment
2287 * boundary for long values.
2288 * offset is then incremented by 4, to indicate the 4 octets which
2289 * have been processed.
2292 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2296 /* unsigned long values must be aligned on a 4 byte boundary */
2297 while( ( (*offset + boundary) % 4) != 0)
2300 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2301 tvb_get_letohl (tvb, *offset);
2308 * Decode an Object type, and display it on the tree.
2311 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2312 gboolean stream_is_big_endian, int boundary) {
2314 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2320 /* Copy a 1 octet sequence from the tvbuff
2321 * which represents a octet, and convert
2322 * it to an octet value.
2323 * offset is then incremented by 1, to indicate the 1 octet which
2324 * has been processed.
2327 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2330 val = tvb_get_guint8(tvb, *offset); /* easy */
2336 /* Copy a sequence of octets from the tvbuff.
2337 * Caller of this function must remember to free the
2338 * array pointed to by seq.
2339 * This function also increments offset by len.
2342 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, guint32 len) {
2345 * Make sure that the entire sequence of octets is in the buffer before
2346 * allocating the buffer, so that we don't have to worry about freeing
2347 * the buffer, and so that we don't try to allocate a buffer bigger
2348 * than the data we'll actually be copying, and thus don't run the risk
2349 * of crashing if the buffer is *so* big that we fail to allocate it
2350 * and "g_new0()" aborts.
2352 tvb_ensure_bytes_exist(tvb, *offset, len);
2355 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2356 * do what we do now, and null-terminate the string (which also means
2357 * we don't need to zero out the entire allocation, just the last byte)?
2359 *seq = g_new0(gchar, len + 1);
2360 tvb_memcpy( tvb, *seq, *offset, len);
2365 /* Copy a 2 octet sequence from the tvbuff
2366 * which represents a signed short value, and convert
2367 * it to a signed short value, taking into account byte order.
2368 * offset is first incremented so that it falls on a proper alignment
2369 * boundary for short values.
2370 * offset is then incremented by 2, to indicate the 2 octets which
2371 * have been processed.
2374 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2378 /* short values must be aligned on a 2 byte boundary */
2379 while( ( (*offset + boundary) % 2) != 0)
2382 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2383 tvb_get_letohs (tvb, *offset);
2391 /* Copy an octet sequence from the tvbuff
2392 * which represents a string, and convert
2393 * it to an string value, taking into account byte order.
2394 * offset is first incremented so that it falls on a proper alignment
2395 * boundary for string values. (begins with an unsigned long LI)
2397 * String sequence is copied to a buffer "seq". This must
2398 * be freed by the calling program.
2399 * offset is then incremented, to indicate the octets which
2400 * have been processed.
2402 * returns number of octets in the sequence
2404 * Note: This function only supports single byte encoding at the
2405 * moment until I get a handle on multibyte encoding etc.
2410 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2415 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2418 (*offset)++; /* must step past \0 delimiter */
2422 get_CDR_octet_seq(tvb, seq, offset, slength);
2424 *seq = g_strdup(""); /* zero-length string */
2427 return slength; /* return length */
2431 /* Process a sequence of octets that represent the
2432 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2434 * This function also increments offset to the correct position.
2436 * It will parse the TypeCode and output data to the "tree" provided
2439 * It returns a guint32 representing a TCKind value.
2442 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2443 gboolean stream_is_big_endian, int boundary,
2444 MessageHeader * header ) {
2447 gint16 s_octet2; /* signed int16 */
2448 guint16 u_octet2; /* unsigned int16 */
2449 guint32 u_octet4; /* unsigned int32 */
2451 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2453 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2454 *offset-sizeof(val),4,val);
2457 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2460 case tk_null: /* empty parameter list */
2462 case tk_void: /* empty parameter list */
2464 case tk_short: /* empty parameter list */
2466 case tk_long: /* empty parameter list */
2468 case tk_ushort: /* empty parameter list */
2470 case tk_ulong: /* empty parameter list */
2472 case tk_float: /* empty parameter list */
2474 case tk_double: /* empty parameter list */
2476 case tk_boolean: /* empty parameter list */
2478 case tk_char: /* empty parameter list */
2480 case tk_octet: /* empty parameter list */
2482 case tk_any: /* empty parameter list */
2484 case tk_TypeCode: /* empty parameter list */
2486 case tk_Principal: /* empty parameter list */
2488 case tk_objref: /* complex parameter list */
2489 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary);
2491 case tk_struct: /* complex parameter list */
2492 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2494 case tk_union: /* complex parameter list */
2495 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2497 case tk_enum: /* complex parameter list */
2498 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary);
2501 case tk_string: /* simple parameter list */
2502 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2504 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2505 *offset-sizeof(u_octet4),4,u_octet4);
2509 case tk_sequence: /* complex parameter list */
2510 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2512 case tk_array: /* complex parameter list */
2513 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2515 case tk_alias: /* complex parameter list */
2516 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2518 case tk_except: /* complex parameter list */
2519 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2521 case tk_longlong: /* empty parameter list */
2523 case tk_ulonglong: /* empty parameter list */
2525 case tk_longdouble: /* empty parameter list */
2527 case tk_wchar: /* empty parameter list */
2529 case tk_wstring: /* simple parameter list */
2530 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2532 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2533 *offset-sizeof(u_octet4),4,u_octet4);
2537 case tk_fixed: /* simple parameter list */
2538 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2540 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2541 *offset-sizeof(u_octet2),2,u_octet2);
2544 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2546 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2547 *offset-sizeof(s_octet2),2,s_octet2);
2551 case tk_value: /* complex parameter list */
2552 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2554 case tk_value_box: /* complex parameter list */
2555 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2557 case tk_native: /* complex parameter list */
2558 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary);
2560 case tk_abstract_interface: /* complex parameter list */
2561 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary );
2564 g_warning("giop: Unknown TCKind %u \n", val);
2573 /* Copy a 4 octet sequence from the tvbuff
2574 * which represents an unsigned long value, and convert
2575 * it to an unsigned long vaule, taking into account byte order.
2576 * offset is first incremented so that it falls on a proper alignment
2577 * boundary for unsigned long values.
2578 * offset is then incremented by 4, to indicate the 4 octets which
2579 * have been processed.
2582 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2586 /* unsigned long values must be aligned on a 4 byte boundary */
2587 while( ( (*offset + boundary) % 4) != 0)
2590 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2591 tvb_get_letohl (tvb, *offset);
2598 /* Copy a 2 octet sequence from the tvbuff
2599 * which represents an unsigned short value, and convert
2600 * it to an unsigned short value, taking into account byte order.
2601 * offset is first incremented so that it falls on a proper alignment
2602 * boundary for unsigned short values.
2603 * offset is then incremented by 2, to indicate the 2 octets which
2604 * have been processed.
2607 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2611 /* unsigned short values must be aligned on a 2 byte boundary */
2612 while( ( (*offset + boundary) % 2) != 0)
2615 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2616 tvb_get_letohs (tvb, *offset);
2624 /* Copy a wchar from the tvbuff.
2625 * Caller of this function must remember to free the
2626 * array pointed to by seq.
2627 * This function also increments offset according to
2630 * For GIOP 1.1 read 2 octets and return size -2. The
2631 * negation means there is no size element in the packet
2632 * and therefore no size to add to the tree.
2634 * For GIOP 1.2 read size of wchar and the size
2635 * octets. size is returned as a gint8.
2637 * For both GIOP versions the wchar is returned
2638 * as a printable string.
2642 /* NOTE: This is very primitive in that it just reads
2643 * the wchar as a series of octets and returns them
2644 * to the user. No translation is attempted based on
2645 * byte orientation, nor on code set. I.e it only
2646 * really reads past the wchar and sets the offset
2650 /* The "decoding" is done according to CORBA chapter 15.
2651 * Wchar is not supported for GIOP 1.0.
2654 gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2659 /* CORBA chapter 15:
2660 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2661 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2662 * followed by the elements of the octet sequence representing
2663 * the encoded value of the wchar.
2666 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2667 slength = 2; /* set for GIOP 1.1 length in octets */
2669 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2670 slength = get_CDR_octet(tvb,offset);
2673 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2674 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2676 /* now turn octets (wchar) into something that can be printed by the user */
2677 *seq = make_printable_string(raw_wstring, slength);
2679 g_free(raw_wstring);
2682 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2683 if (header->GIOP_version.minor < 2)
2686 return slength; /* return length */
2691 /* Copy a wstring from the tvbuff.
2692 * Caller of this function must remember to free the
2693 * array pointed to by seq.
2694 * This function also increments offset, according to
2695 * wstring length. length is returned as guint32
2698 /* NOTE: This is very primitive in that it just reads
2699 * the wstring as a series of octets and returns them
2700 * to the user. No translation is attempted based on
2701 * byte orientation, nor on code set. I.e it only
2702 * really reads past the wstring and sets the offset
2706 /* The "decoding" is done according to CORBA chapter 15.
2707 * Wstring is not supported for GIOP 1.0.
2711 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2712 int boundary, MessageHeader * header) {
2717 /* CORBA chapter 15:
2718 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2719 * length and string are NUL terminated (length???).
2720 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2724 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2726 /* get length, same for all GIOP versions,
2727 * although for 1.2 CORBA doesnt say, so assume.
2729 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2733 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2734 slength = 5; /* better than core dumping during debug */
2738 if (header->GIOP_version.minor < 2) {
2740 (*offset)++; /* must step past \0 delimiter */
2742 /* assume length is number of characters and not octets, spec not clear */
2743 slength = slength * 2; /* length in octets is 2 * wstring length */
2747 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2749 /* now turn octets (wstring) into something that can be printed by the user */
2750 *seq = make_printable_string(raw_wstring, slength);
2752 g_free(raw_wstring);
2755 return slength; /* return length */
2762 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2764 * typedef short AddressingDisposition;
2765 * const short KeyAddr = 0;
2766 * const short ProfileAddr = 1;
2767 * const short ReferenceAddr = 2;
2768 * struct IORAddressingInfo {
2769 * unsigned long selected_profile_index;
2773 * union TargetAddress switch (AddressingDisposition) {
2774 * case KeyAddr: sequence <octet> object_key;
2775 * case ProfileAddr: IOP::TaggedProfile profile;
2776 * case ReferenceAddr: IORAddressingInfo ior;
2781 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2782 gboolean stream_is_big_endian)
2784 guint16 discriminant;
2786 gchar *p_object_key;
2790 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2793 proto_tree_add_text (tree, tvb, *offset -2, 2,
2794 "TargetAddress Discriminant: %u", discriminant);
2797 switch (discriminant)
2799 case 0: /* KeyAddr */
2800 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2803 proto_tree_add_text (tree, tvb, *offset -4, 4,
2804 "KeyAddr (object key length): %u", len);
2809 get_CDR_octet_seq(tvb, &object_key, offset, len);
2810 p_object_key = make_printable_string( object_key, len );
2814 proto_tree_add_text (tree, tvb, *offset -len, len,
2815 "KeyAddr (object key): %s", p_object_key);
2817 g_free( p_object_key );
2818 g_free( object_key );
2821 case 1: /* ProfileAddr */
2822 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2823 stream_is_big_endian, NULL);
2825 case 2: /* ReferenceAddr */
2826 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2830 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2831 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2834 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2842 dissect_reply_body (tvbuff_t *tvb, guint offset, packet_info *pinfo,
2843 proto_tree *tree, gboolean stream_is_big_endian,
2844 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2846 guint sequence_length;
2847 gboolean exres = FALSE; /* result of trying explicit dissectors */
2848 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2851 * comp_req_list stuff
2854 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2858 switch (reply_status)
2860 case SYSTEM_EXCEPTION:
2862 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2865 case USER_EXCEPTION:
2867 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2871 proto_tree_add_text(tree, tvb, offset-4, 4,
2872 "Exception length: %u", sequence_length);
2874 if (sequence_length != 0)
2878 proto_tree_add_text(tree, tvb, offset, sequence_length,
2880 tvb_format_text(tvb, offset, sequence_length));
2884 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2886 /* read exception id from buffer and store in*/
2888 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2894 offset += sequence_length;
2900 * Now just fall through to the NO_EXCEPTION part
2901 * as this is common .
2909 /* lookup MFN in hash directly */
2911 mfn = get_mfn_from_fn(pinfo->fd->num);
2913 if (mfn == pinfo->fd->num)
2914 return; /* no matching frame number, what am I */
2916 /* get entry for this MFN */
2917 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2920 return; /* no matching entry */
2924 * If this packet is a REPLY to a RESOLVE(request)
2926 * TODO - make this lookup faster -- FS
2929 if (!strcmp(giop_op_resolve,entry->operation)) {
2930 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2934 /* TODO -- Put stuff here for other "interesting operations" */
2938 * Call sub dissector.
2939 * First try an find a explicit sub_dissector, then if that
2940 * fails, try the heuristic method.
2945 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
2948 /* Only call heuristic if no explicit dixxector was found */
2951 try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
2957 case LOCATION_FORWARD:
2958 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2962 case LOCATION_FORWARD_PERM:
2963 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2967 case NEEDS_ADDRESSING_MODE: {
2969 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2971 proto_tree_add_text (tree, tvb, offset -2, 2,
2972 "AddressingDisposition: %u", addr_disp);
2980 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
2986 g_free(repoid); /* free resource */
2996 /* The format of the Reply Header for GIOP 1.0 and 1.1
2997 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
2999 struct ReplyHeader_1_0 {
3000 IOP::ServiceContextList service_context;
3001 unsigned long request_id;
3002 ReplyStatusType_1_0 reply_status;
3006 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3007 MessageHeader * header,
3008 gboolean stream_is_big_endian) {
3012 guint32 reply_status;
3013 proto_tree *reply_tree = NULL;
3015 guint32 mfn; /* matching frame number */
3018 tf = proto_tree_add_text (tree, tvb, offset, -1,
3019 "General Inter-ORB Protocol Reply");
3020 if (reply_tree == NULL)
3022 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3028 * Decode IOP::ServiceContextList
3031 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3033 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3035 if (check_col(pinfo->cinfo, COL_INFO)) {
3036 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3040 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3041 "Request id: %u", request_id);
3044 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3046 if (check_col(pinfo->cinfo, COL_INFO)) {
3047 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3048 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3053 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3055 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3060 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3063 if (! pinfo->fd->flags.visited) {
3064 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3065 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3066 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3070 header->req_id = request_id; /* save for sub dissector */
3071 header->rep_status = reply_status; /* save for sub dissector */
3073 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3074 reply_status, header,tree);
3079 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3080 * and 1.1 header, only the fields have been rearranged. From Section
3081 * 15.4.3.1 of the CORBA 2.4 specification:
3083 * struct ReplyHeader_1_2 {
3084 * unsigned long request_id;
3085 * ReplyStatusType_1_2 reply_status;
3086 * IOP:ServiceContextList service_context;
3090 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3092 MessageHeader * header,
3093 gboolean stream_is_big_endian) {
3097 guint32 reply_status;
3098 proto_tree *reply_tree = NULL;
3100 guint32 mfn; /* matching frame number */
3103 tf = proto_tree_add_text (tree, tvb, offset, -1,
3104 "General Inter-ORB Protocol Reply");
3105 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3108 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3110 if (check_col(pinfo->cinfo, COL_INFO)) {
3111 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3115 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3116 "Request id: %u", request_id);
3119 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3121 if (check_col(pinfo->cinfo, COL_INFO)) {
3122 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3123 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3128 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3130 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3135 * Decode IOP::ServiceContextList
3138 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3141 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3144 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3147 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3150 if (! pinfo->fd->flags.visited) {
3151 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3152 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3153 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3158 * Add header to argument list so sub dissector can get header info.
3161 header->req_id = request_id; /* save for sub dissector */
3162 header->rep_status = reply_status; /* save for sub dissector */
3164 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3165 reply_status,header,tree);
3171 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3173 gboolean stream_is_big_endian) {
3177 proto_tree *cancel_request_tree = NULL;
3181 tf = proto_tree_add_text (tree, tvb, offset, -1,
3182 "General Inter-ORB Protocol CancelRequest");
3183 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3186 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3188 if (check_col(pinfo->cinfo, COL_INFO)) {
3189 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3193 proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4,
3194 "Request id: %u", request_id);
3200 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3201 * in section 15.4.2.1 of the CORBA 2.4 specification.
3203 * struct RequestHeader{
3204 * IOP::ServiceContextList service_context;
3205 * unsigned long request_id;
3206 * boolean response_expected;
3207 * octet reserved[3]; // Only in GIOP 1.1
3208 * sequence<octet> object_key;
3210 * CORBA::OctetSeq requesting_principal;
3214 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3216 MessageHeader * header, gboolean stream_is_big_endian)
3222 guint32 objkey_len = 0; /* object key length */
3223 gchar *objkey = NULL; /* object key sequence */
3224 gchar *print_objkey; /* printable object key sequence */
3225 gboolean exres = FALSE; /* result of trying explicit dissectors */
3228 gchar *requesting_principal;
3229 gchar *print_requesting_principal;
3230 guint8 response_expected;
3232 proto_tree *request_tree = NULL;
3235 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3240 tf = proto_tree_add_text (tree, tvb, offset, -1,
3241 "General Inter-ORB Protocol Request");
3242 if (request_tree == NULL)
3244 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3252 * Decode IOP::ServiceContextList
3255 decode_ServiceContextList(tvb, request_tree, &offset,stream_is_big_endian, 0);
3258 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3259 if (check_col(pinfo->cinfo, COL_INFO))
3261 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3265 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3266 "Request id: %u", request_id);
3269 response_expected = tvb_get_guint8( tvb, offset );
3271 if (check_col(pinfo->cinfo, COL_INFO))
3273 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3274 response_expected ? "two-way" : "one-way");
3278 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3279 "Response expected: %u", response_expected);
3282 if( header->GIOP_version.minor > 0)
3284 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3287 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3288 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3295 /* Length of object_key sequence */
3296 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3301 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3302 /**/ "Object Key length: %u", objkey_len);
3307 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3309 print_objkey = make_printable_string(objkey, objkey_len);
3313 proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
3314 /**/ "Object Key: %s", print_objkey);
3318 g_free( print_objkey );
3322 * Register a cleanup function in case on of our tvbuff accesses
3323 * throws an exception. We need to clean up objkey.
3325 CLEANUP_PUSH(g_free, objkey);
3327 /* length of operation string and string */
3328 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3331 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3332 /**/ "Operation length: %u", len);
3337 if (check_col(pinfo->cinfo, COL_INFO))
3339 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3343 proto_tree_add_text (request_tree, tvb, offset - len, len,
3344 /**/ "Operation: %s", operation);
3350 * Register a cleanup function in case on of our tvbuff accesses
3351 * throws an exception. We need to clean up operation.
3353 CLEANUP_PUSH(g_free, operation);
3355 /* length of requesting_principal string */
3356 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3359 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3360 /**/ "Requesting Principal Length: %u", len);
3365 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3367 print_requesting_principal = make_printable_string(requesting_principal, len);
3371 proto_tree_add_text (request_tree, tvb, offset - len, len,
3372 /**/ "Requesting Principal: %s", print_requesting_principal);
3376 g_free( print_requesting_principal );
3377 g_free( requesting_principal );
3382 * Save FN,reqid,and operation for later. Add sub_handle later.
3383 * But only if user is NOT clicking.
3386 if (! pinfo->fd->flags.visited)
3387 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3388 request_id,operation,NULL);
3392 * Call subdissector here before freeing "operation" and "key"
3393 * pass request_id also.
3394 * First try an find an explicit sub_dissector, then if that
3395 * fails, try the heuristic method.
3400 header->req_id = request_id; /* save for sub dissector */
3401 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3405 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3408 /* Only call heuristic if no explicit dissector was found */
3411 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3416 * We're done with operation, so we can call the cleanup handler to free
3417 * it, and then pop the cleanup handler.
3419 CLEANUP_CALL_AND_POP;
3422 * We're done with objkey, so we can call the cleanup handler to free
3423 * it, and then pop the cleanup handler.
3425 CLEANUP_CALL_AND_POP;
3429 /** The format of a GIOP 1.2 RequestHeader message is
3430 * (CORBA 2.4, sec. 15.4.2):
3432 * struct RequestHeader_1_2 {
3433 * unsigned long request_id;
3434 * octet response_flags;
3435 * octet reserved[3];
3436 * TargetAddress target;
3438 * IOP::ServiceContextList service_context;
3439 * // requesting_principal not in GIOP 1.2
3443 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3445 MessageHeader * header, gboolean stream_is_big_endian)
3450 guint8 response_flags;
3452 gchar *operation = NULL;
3453 proto_tree *request_tree = NULL;
3455 gboolean exres = FALSE; /* result of trying explicit dissectors */
3457 gchar *repoid = NULL;
3462 tf = proto_tree_add_text (tree, tvb, offset, -1,
3463 "General Inter-ORB Protocol Request");
3464 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3467 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3468 if (check_col(pinfo->cinfo, COL_INFO))
3470 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3474 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3475 "Request id: %u", request_id);
3478 response_flags = tvb_get_guint8( tvb, offset );
3482 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3483 "Response flags: %s (%u)",
3484 match_strval(response_flags, sync_scope),
3488 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3491 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3492 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3496 dissect_target_address(tvb, pinfo, &offset, request_tree, stream_is_big_endian);
3498 /* length of operation string */
3499 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3502 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3503 /**/ "Operation length: %u", len);
3508 if (check_col(pinfo->cinfo, COL_INFO))
3510 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3514 proto_tree_add_text (request_tree, tvb, offset - len, len,
3515 /**/ "Operation: %s", operation);
3522 * Register a cleanup function in case on of our tvbuff accesses
3523 * throws an exception. We need to clean up operation.
3525 CLEANUP_PUSH(g_free, operation);
3528 * Decode IOP::ServiceContextList
3531 decode_ServiceContextList(tvb, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3534 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3535 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3536 * GIOP octet stream start.
3539 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3542 * Save FN,reqid,and operation for later. Add sub_handle later.
3543 * But only if user is NOT clicking.
3546 if (! pinfo->fd->flags.visited)
3547 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3548 request_id,operation,NULL);
3552 * Call sub dissector.
3553 * First try an find a explicit sub_dissector, then if that
3554 * fails, try the heuristic method.
3559 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3562 /* Only call heuristic if no explicit dissector was found */
3565 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3570 * We're done with operation, so we can call the cleanup handler to free
3571 * it, and then pop the cleanup handler.
3573 CLEANUP_CALL_AND_POP;
3577 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3578 proto_tree * tree, MessageHeader * header,
3579 gboolean stream_is_big_endian)
3585 gchar *p_object_key;
3586 proto_tree *locate_request_tree = NULL;
3591 tf = proto_tree_add_text (tree, tvb, offset, -1,
3592 "General Inter-ORB Locate Request");
3593 if (locate_request_tree == NULL)
3595 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3600 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3601 if (check_col(pinfo->cinfo, COL_INFO))
3603 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3605 if (locate_request_tree)
3607 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3608 "Request id: %u", request_id);
3611 if(header->GIOP_version.minor < 2)
3613 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3614 if (locate_request_tree)
3616 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3617 "Object Key length: %u", len);
3621 get_CDR_octet_seq(tvb, &object_key, &offset, len);
3623 p_object_key = make_printable_string(object_key, len);
3625 if(locate_request_tree)
3628 proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
3629 "Object Key: %s", p_object_key);
3632 g_free(p_object_key);
3636 else /* GIOP 1.2 and higher */
3638 dissect_target_address(tvb, pinfo, &offset, locate_request_tree,
3639 stream_is_big_endian);
3645 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3646 proto_tree * tree, MessageHeader * header,
3647 gboolean stream_is_big_endian)
3651 guint32 locate_status;
3654 proto_tree *locate_reply_tree = NULL;
3659 tf = proto_tree_add_text (tree, tvb, offset, -1,
3660 "General Inter-ORB Locate Reply");
3661 if (locate_reply_tree == NULL)
3663 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3668 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3669 if (check_col(pinfo->cinfo, COL_INFO))
3671 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3673 if (locate_reply_tree)
3675 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3676 "Request id: %u", request_id);
3679 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3680 if (locate_reply_tree)
3682 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3683 "Locate status: %s",
3684 match_strval(locate_status, giop_locate_status_types)
3688 /* Decode the LocateReply body.
3690 * For GIOP 1.0 and 1.1 body immediately follows header.
3691 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3695 if (header->GIOP_version.minor > 1) {
3696 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3700 switch(locate_status) {
3701 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3702 case OBJECT_FORWARD_PERM:
3703 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3705 case LOC_SYSTEM_EXCEPTION:
3706 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3708 case LOC_NEEDS_ADDRESSING_MODE:
3709 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3710 if(locate_reply_tree) {
3711 proto_tree_add_text (tree, tvb, offset -2, 2,
3712 "AddressingDisposition: %u", addr_disp);
3715 default: /* others have no reply body */
3722 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3723 gboolean stream_is_big_endian)
3727 proto_tree *fragment_tree = NULL;
3732 tf = proto_tree_add_text (tree, tvb, offset, -1,
3733 "General Inter-ORB Fragment");
3734 if (fragment_tree == NULL)
3736 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3741 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3742 if (check_col(pinfo->cinfo, COL_INFO))
3744 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3748 proto_tree_add_text (fragment_tree, tvb, offset-4, 4,
3749 "Request id: %u", request_id);
3755 /* Main entry point */
3757 gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3759 MessageHeader header;
3760 tvbuff_t *giop_header_tvb;
3761 tvbuff_t *payload_tvb;
3763 proto_tree *clnp_tree = NULL;
3766 guint minor_version;
3767 gboolean stream_is_big_endian;
3773 giop_dump_collection(cd_module_hash);
3774 giop_dump_collection(cd_objkey_hash);
3775 giop_dump_collection(cd_heuristic_users);
3776 giop_dump_collection(cd_complete_reply_hash);
3777 giop_dump_collection(cd_complete_request_list);
3780 header.exception_id = NULL;
3782 /* check magic number and version */
3785 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
3787 if (tvb_length_remaining(tvb, 0) < GIOP_HEADER_SIZE)
3789 /* Not enough data captured to hold the GIOP header; don't try
3790 to interpret it as GIOP. */
3794 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3795 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3798 * because I have added extra elements in MessageHeader struct
3799 * for sub dissectors. -- FS
3802 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3804 if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
3806 /* Not a GIOP message. */
3811 if (check_col (pinfo->cinfo, COL_PROTOCOL))
3813 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3816 if (header.GIOP_version.major != GIOP_MAJOR ||
3817 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3819 /* Bad version number; should we note that and dissect the rest
3820 as data, or should we return FALSE on the theory that it
3821 might have been some other packet that happened to begin with
3822 "GIOP"? We shouldn't do *both*, so we return TRUE, for now.
3823 If we should return FALSE, we should do so *without* setting
3824 the "Info" column, *without* setting the "Protocol" column,
3825 and *without* adding anything to the protocol tree. */
3827 if (check_col (pinfo->cinfo, COL_INFO))
3829 col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3830 header.GIOP_version.major, header.GIOP_version.minor);
3834 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3835 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3836 proto_tree_add_text (clnp_tree, giop_header_tvb, 0, -1,
3837 "Version %u.%u not supported",
3838 header.GIOP_version.major,
3839 header.GIOP_version.minor);
3841 call_dissector(data_handle,payload_tvb, pinfo, tree);
3845 if (check_col (pinfo->cinfo, COL_INFO))
3847 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3848 header.GIOP_version.major, header.GIOP_version.minor,
3849 val_to_str(header.message_type, giop_message_types,
3850 "Unknown message type (0x%02x)"));
3853 stream_is_big_endian = is_big_endian (&header);
3855 if (stream_is_big_endian)
3856 message_size = pntohl (&header.message_size);
3858 message_size = pletohl (&header.message_size);
3862 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, 12, FALSE);
3863 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3864 proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3865 "Magic number: %s", GIOP_MAGIC);
3866 proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3868 header.GIOP_version.major,
3869 header.GIOP_version.minor);
3870 switch (minor_version)
3874 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3875 "Flags: 0x%02x (%s %s)",
3877 (stream_is_big_endian) ? "big-endian" : "little-endian",
3878 (header.flags & 0x02) ? " fragment" : "");
3881 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3882 "Byte ordering: %s-endian",
3883 (stream_is_big_endian) ? "big" : "little");
3887 } /* minor_version */
3889 proto_tree_add_uint_format (clnp_tree,
3890 hf_giop_message_type,
3891 giop_header_tvb, 7, 1,
3892 header.message_type,
3893 "Message type: %s", match_strval(header.message_type, giop_message_types));
3895 proto_tree_add_uint (clnp_tree,
3896 hf_giop_message_size,
3897 giop_header_tvb, 8, 4, message_size);
3902 if (check_col (pinfo->cinfo, COL_INFO))
3904 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3905 header.GIOP_version.major, header.GIOP_version.minor,
3906 match_strval(header.message_type, giop_message_types));
3910 switch (header.message_type)
3914 if(header.GIOP_version.minor < 2)
3916 dissect_giop_request_1_1 (payload_tvb, pinfo, tree,
3917 &header, stream_is_big_endian);
3921 dissect_giop_request_1_2 (payload_tvb, pinfo, tree,
3922 &header, stream_is_big_endian);
3929 if(header.GIOP_version.minor < 2)
3931 dissect_giop_reply (payload_tvb, pinfo, tree, &header,
3932 stream_is_big_endian);
3936 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree,
3937 &header, stream_is_big_endian);
3941 dissect_giop_cancel_request(payload_tvb, pinfo, tree,
3942 stream_is_big_endian);
3945 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
3946 stream_is_big_endian);
3949 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
3950 stream_is_big_endian);
3953 dissect_giop_fragment(payload_tvb, pinfo, tree,
3954 stream_is_big_endian);
3959 } /* switch message_type */
3963 * XXX - we should catch exceptions here, so that we can free
3964 * this if an exception is thrown.
3965 * We'd then have to forward the exception.
3967 if (header.exception_id != NULL)
3968 g_free(header.exception_id);
3974 proto_register_giop (void)
3976 static hf_register_info hf[] = {
3977 { &hf_giop_message_type,
3978 { "Message type", "giop.type",
3979 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
3982 { &hf_giop_message_size,
3983 { "Message size", "giop.len",
3984 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3988 { "Repository ID", "giop.repoid",
3989 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
3992 { &hf_giop_string_length,
3993 { "String Length", "giop.strlen",
3994 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3997 { &hf_giop_sequence_length,
3998 { "Sequence Length", "giop.seqlen",
3999 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4002 { &hf_giop_profile_id,
4003 { "Profile ID", "giop.profid",
4004 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
4009 { "IOR::type_id", "giop.typeid",
4010 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4013 { &hf_giop_iiop_v_maj,
4014 { "IIOP Major Version", "giop.iiop_vmaj",
4015 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4018 { &hf_giop_iiop_v_min,
4019 { "IIOP Minor Version", "giop.iiop_vmin",
4020 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4023 { &hf_giop_endianess,
4024 { "Endianess", "giop.endianess",
4025 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4028 { &hf_giop_IIOP_tag,
4029 { "IIOP Component TAG", "giop.iioptag",
4030 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4034 { "IOR Profile TAG", "giop.iortag",
4035 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4039 { "TypeCode enum", "giop.TCKind",
4040 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4043 { &hf_giop_typecode_count,
4044 { "TypeCode count", "giop.tccount",
4045 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4048 { &hf_giop_typecode_default_used,
4049 { "default_used", "giop.tcdefault_used",
4050 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4053 { &hf_giop_typecode_digits,
4054 { "Digits", "giop.tcdigits",
4055 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4059 { &hf_giop_typecode_length,
4060 { "Length", "giop.tclength",
4061 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4064 { &hf_giop_typecode_max_length,
4065 { "Maximum length", "giop.tcmaxlen",
4066 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4069 { &hf_giop_typecode_member_name,
4070 { "TypeCode member name", "giop.tcmemname",
4071 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4074 { &hf_giop_typecode_name,
4075 { "TypeCode name", "giop.tcname",
4076 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4079 { &hf_giop_typecode_scale,
4080 { "Scale", "giop.tcscale",
4081 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4084 { &hf_giop_typecode_ValueModifier,
4085 { "ValueModifier", "giop.tcValueModifier",
4086 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4089 { &hf_giop_typecode_Visibility,
4090 { "Visibility", "giop.tcVisibility",
4091 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4096 { &hf_giop_type_boolean,
4097 { "TypeCode boolean data", "giop.tcboolean",
4098 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4101 { &hf_giop_type_char,
4102 { "TypeCode char data", "giop.tcchar",
4103 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4106 { &hf_giop_type_double,
4107 { "TypeCode double data", "giop.tcdouble",
4108 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4111 { &hf_giop_type_enum,
4112 { "TypeCode enum data", "giop.tcenumdata",
4113 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4117 * float as double ?? -- FIX
4120 { &hf_giop_type_float,
4121 { "TypeCode float data", "giop.tcfloat",
4122 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4125 { &hf_giop_type_long,
4126 { "TypeCode long data", "giop.tclongdata",
4127 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4130 { &hf_giop_type_octet,
4131 { "TypeCode octet data", "giop.tcoctet",
4132 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4135 { &hf_giop_type_short,
4136 { "TypeCode short data", "giop.tcshortdata",
4137 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4140 { &hf_giop_type_string,
4141 { "TypeCode string data", "giop.tcstring",
4142 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4145 { &hf_giop_type_ulong,
4146 { "TypeCode ulong data", "giop.tculongdata",
4147 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4150 { &hf_giop_type_ushort,
4151 { "TypeCode ushort data", "giop.tcushortdata",
4152 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4156 * IIOP Module - Chapter 15.10.2
4159 { &hf_giop_iiop_host,
4160 { "IIOP::Profile_host", "giop.iiop.host",
4161 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4165 { &hf_giop_iiop_port,
4166 { "IIOP::Profile_port", "giop.iiop.port",
4167 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4172 * IIOP ServiceContext
4175 { &hf_giop_iop_vscid,
4176 { "VSCID", "giop.iiop.vscid",
4177 FT_UINT32, BASE_HEX, NULL, 0xffffff00, "", HFILL }
4181 { &hf_giop_iop_scid,
4182 { "SCID", "giop.iiop.scid",
4183 FT_UINT32, BASE_HEX, NULL, 0x000000ff, "", HFILL }
4190 static gint *ett[] = {
4194 &ett_giop_cancel_request,
4195 &ett_giop_locate_request,
4196 &ett_giop_locate_reply,
4203 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4205 proto_register_field_array (proto_giop, hf, array_length (hf));
4206 proto_register_subtree_array (ett, array_length (ett));
4209 /* register init routine */
4211 register_init_routine( &giop_init); /* any init stuff */
4214 * Init the giop user module hash tables here, as giop users
4215 * will populate it via register_giop_user_module BEFORE my
4216 * own giop_init() is called.
4219 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4221 giop_module_keys = g_mem_chunk_new("giop_module_keys",
4222 sizeof(struct giop_module_key),
4223 giop_module_init_count * sizeof(struct giop_module_key),
4226 giop_module_vals = g_mem_chunk_new("giop_module_vals",
4227 sizeof(struct giop_module_val),
4228 giop_module_init_count * sizeof(struct giop_module_val),
4235 void proto_reg_handoff_giop (void) {
4236 data_handle = find_dissector("data");
4237 heur_dissector_add("tcp", dissect_giop, proto_giop);
4238 /* Support DIOP (GIOP/UDP) */
4239 heur_dissector_add("udp", dissect_giop, proto_giop);
4248 * Ref Corba v2.4.2 Chapter 13
4256 typedef unsigned long ProfileId;
4258 const ProfileId TAG_INTERNET_IOP = 0;
4259 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4261 struct TaggedProfile {
4263 sequence <octet> profile_data;
4268 sequence <TaggedProfile> profiles;
4271 typedef unsigned long ComponentId;
4273 struct TaggedComponent {
4275 sequence <octet> component_data;
4278 typedef sequence <TaggedComponent> MultipleComponentProfile;
4284 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4285 guint32 boundary, gboolean stream_is_big_endian) {
4288 guint32 seqlen_p; /* sequence length of profiles */
4291 proto_tree *tree = NULL; /* IOR tree */
4294 gchar *repobuf; /* for repository ID */
4298 /* create a subtree */
4301 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
4302 tree = proto_item_add_subtree (tf, ett_giop_ior);
4306 /* Get type_id == Repository ID */
4308 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4311 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4312 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4314 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4315 *offset-u_octet4,u_octet4,repobuf);
4320 * Register a cleanup function in case on of our tvbuff accesses
4321 * throws an exception. We need to clean up repobuf.
4322 * We can't free it yet, as we must wait until we have the object
4323 * key, as we have to add both to the hash table.
4325 CLEANUP_PUSH(g_free, repobuf);
4327 /* Now get a sequence of profiles */
4328 /* Get sequence length (number of elements) */
4330 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4332 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4333 *offset-sizeof(seqlen_p),4,seqlen_p);
4337 /* fetch all TaggedProfiles in this sequence */
4339 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4340 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4344 * We're done with repobuf, so we can call the cleanup handler to free
4345 * it, and then pop the cleanup handler.
4347 CLEANUP_CALL_AND_POP;
4351 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4352 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4354 guint32 seqlen_pd; /* sequence length of profile data */
4356 guint32 pidtag; /* profile ID TAG */
4358 gchar *profile_data; /* profile_data pointer */
4359 gchar *p_profile_data; /* printable profile_data pointer */
4361 guint32 new_boundary; /* for encapsulations encountered */
4362 gboolean new_big_endianess; /* for encapsulations encountered */
4364 /* Get ProfileId tag */
4366 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4369 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4370 *offset-sizeof(pidtag),4,pidtag);
4373 /* get sequence length, new endianness and boundary for encapsulation */
4375 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4376 stream_is_big_endian, boundary,
4377 &new_big_endianess, &new_boundary);
4379 /* return if zero length sequence */
4386 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4387 * decode it, otherwise just dump the octet sequence
4389 * also, store IOR in our objectkey hash
4391 * TODO - handle other TAGS
4395 case IOP_TAG_INTERNET_IOP:
4397 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4402 /* fetch all octets in this sequence , but skip endianess */
4404 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4406 /* Make a printable string */
4408 p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4411 proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4412 "Profile Data: %s", p_profile_data);
4415 g_free(p_profile_data);
4417 g_free(profile_data);
4428 * Decode IIOP IOR Profile
4429 * Ref Chap 15.7.2 in Corba Spec
4433 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4434 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4435 gboolean store_flag) {
4437 guint32 i; /* loop index */
4439 guint8 v_major,v_minor; /* IIOP sersion */
4441 guint32 u_octet4; /* u long */
4442 guint16 u_octet2; /* u short */
4443 guint32 seqlen; /* generic sequence length */
4444 guint32 seqlen1; /* generic sequence length */
4445 gchar *objkey; /* object key pointer */
4446 gchar *p_chars; /* printable characters pointer */
4449 /* Get major/minor version */
4451 v_major = get_CDR_octet(tvb,offset);
4452 v_minor = get_CDR_octet(tvb,offset);
4456 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4457 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4458 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4459 *offset-sizeof(v_minor),1,v_minor );
4465 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4468 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4469 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4471 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4472 *offset-u_octet4,u_octet4,buf);
4476 g_free(buf); /* dont forget */
4480 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4483 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4484 *offset-sizeof(u_octet2),2,u_octet2);
4488 /* Object Key - sequence<octet> object_key */
4490 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4493 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4494 *offset-sizeof(seqlen),4,seqlen);
4498 /* fetch all octets in this sequence */
4499 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4502 * Now we may have the Repository ID from earlier, as well
4503 * as the object key sequence and lengh. So lets store them in
4504 * our objectkey hash and free buffers.
4506 * But only insert if user is not clicking and repo id not NULL.
4512 if(!pinfo->fd->flags.visited)
4513 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4518 * No pinfo, but store anyway if flag set. eg: IOR read from file
4522 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4526 /* Make a printable string */
4528 p_chars = make_printable_string( objkey, seqlen );
4531 proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
4532 "Object Key: %s", p_chars);
4540 * Now see if if its v1.1 or 1.2, as they can contain
4541 * extra sequence of IOP::TaggedComponents
4554 /* sequence of IOP::TaggedComponents */
4555 /* Ref Chap 13 in Corba Spec */
4557 /* get sequence length */
4558 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4561 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4562 *offset-sizeof(seqlen),4,seqlen);
4565 for (i=0; i< seqlen; i++) {
4567 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4569 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4570 *offset-sizeof(u_octet4),4,u_octet4);
4573 /* get component_data */
4574 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4576 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4577 *offset-sizeof(seqlen1),4,seqlen1);
4581 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4584 /* Make a printable string of data */
4586 p_chars = make_printable_string(buf, seqlen1);
4588 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4589 "component_data: %s", p_chars);
4603 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4610 * From Section 13.10.2.5 of the CORBA 3.0 spec.
4612 * module CONV_FRAME {
4613 * typedef unsigned long CodeSetId;
4614 * struct CodeSetContext {
4615 * CodeSetId char_data;
4616 * CodeSetId wchar_data;
4620 * Code sets are identified by a 32-bit integer id from OSF.
4621 * See: ftp://ftp.opengroup.org/pub/code_set_registry
4623 static void decode_CodeSets(tvbuff_t *tvb, proto_tree *tree, int *offset,
4624 gboolean stream_is_be, guint32 boundary) {
4626 /* The boundary being passed in is the offset where the context_data
4627 * sequence begins. */
4629 guint32 code_set_id;
4631 /* We pass in -boundary, because the alignment is calculated relative to
4632 the beginning of the context_data sequence.
4633 Inside get_CDR_ulong(), the calculation will be (offset +(- boundary)) % 4
4634 to determine the correct alignment of the short. */
4635 code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
4637 proto_tree_add_text (tree, tvb, *offset - 4, 4,
4638 "char_data: 0x%08x", code_set_id);
4640 code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
4642 proto_tree_add_text (tree, tvb, *offset - 4, 4,
4643 "wchar_data: 0x%08x", code_set_id);
4649 * From Section 2.7.3 of the Real-time CORBA 1.1 Standard, the CORBA priority
4650 * is represented in the GIOP service request as:
4653 * typedef short ServiceId;
4654 * const ServiceId RTCorbaPriority = 10;
4657 * The RT-CORBA priority is a CDR encoded short value in a sequence<octet>
4660 static void decode_RTCorbaPriority(tvbuff_t *tvb, proto_tree *tree, int *offset,
4661 gboolean stream_is_be, guint32 boundary) {
4663 /* The boundary being passed in is the offset where the context_data
4664 * sequence begins. */
4668 /* RTCorbaPriority is stored as a CDR encoded short */
4669 /* We pass in -boundary, because the alignment is calculated relative to
4670 the beginning of the context_data sequence.
4671 Inside get_CDR_short(), the calculation will be (offset + (- boundary)) % 2
4672 to determine the correct alignment of the short. */
4673 rtpriority = get_CDR_short(tvb, offset, stream_is_be, -((gint32) boundary) );
4676 /* Highlight all of context_data except for the first endian byte */
4677 proto_tree_add_text (tree, tvb, *offset - 2, 2,
4678 "RTCorbaPriority: %d", rtpriority);
4683 static void decode_UnknownServiceContext(tvbuff_t *tvb, proto_tree *tree, int *offset,
4684 gboolean stream_is_be, guint32 boundary) {
4686 guint32 context_data_len;
4687 gchar *p_context_data;
4688 gchar *context_data;
4690 /* get sequence length, and NO encapsulation */
4691 context_data_len = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4694 /* return if zero length sequence */
4695 if(context_data_len == 0)
4699 * Now decode sequence according to vendor ServiceId, but I dont
4700 * have that yet, so just dump it as data.
4703 /* fetch all octets in this sequence */
4705 get_CDR_octet_seq(tvb, &context_data, offset, context_data_len);
4707 /* Make a printable string */
4709 p_context_data = make_printable_string( context_data, context_data_len );
4712 proto_tree_add_text (tree, tvb, *offset - context_data_len , context_data_len,
4713 "context_data: %s", p_context_data);
4716 g_free(context_data);
4717 g_free(p_context_data);
4725 * typedef unsigned long ServiceID;
4727 * struct ServiceContext {
4728 * ServiceID context_id;
4729 * sequence <octet> context_data;
4731 * typedef sequence <ServiceContext> ServiceContextList;
4734 * Note: Spec says context_data is an encapsulation.
4739 void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *ptree, int *offset,
4740 gboolean stream_is_be, guint32 boundary) {
4742 guint32 seqlen; /* sequence length */
4743 guint32 context_data_len; /* context data sequence length */
4745 proto_tree *tree = NULL; /* ServiceContext tree */
4746 proto_tree *sub_tree1 = NULL;
4747 proto_item *tf = NULL, *tf_st1;
4752 guint32 vscid; /* Vendor Service context id */
4754 const gchar *service_context_name;
4755 gboolean encapsulation_is_be;
4756 guint32 encapsulation_boundary;
4757 int temp_offset, temp_offset1;
4758 int start_offset = *offset;
4760 /* create a subtree */
4763 /* set length to 0 now and correct with proto_item_set_len() later */
4764 tf = proto_tree_add_text (ptree, tvb, *offset, 0, "ServiceContextList");
4766 tree = proto_item_add_subtree (tf, ett_giop_scl);
4769 /* Get sequence length (number of elements) */
4770 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4773 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4774 *offset-sizeof(seqlen),4,seqlen);
4777 /* return if zero length sequence */
4781 proto_item_set_len(tf, *offset - start_offset);
4786 /* Loop for all ServiceContext's */
4788 for (i=0; i<seqlen; i++) {
4790 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4791 vscid = (context_id & 0xffffff00) >> 8; /* vendor info, top 24 bits */
4792 scid = context_id & 0x000000ff; /* standard service info, lower 8 bits */
4795 proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4796 *offset-sizeof(guint32),4,vscid);
4798 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4799 *offset-sizeof(guint32),4,scid);
4803 if( vscid == 0) { /* OMG specified */
4804 service_context_name = match_strval(scid, service_context_ids);
4805 } else { /* Proprietary vscid */
4806 service_context_name = NULL;
4809 if ( service_context_name == NULL ) {
4810 service_context_name = "Unknown";
4814 proto_tree_add_text (tree, tvb, *offset -sizeof(context_id), 4,
4815 "Service Context ID: %s (%u)", service_context_name,
4819 temp_offset1 = *offset;
4820 /* The OMG has vscid of 0 reserved */
4821 if( vscid != 0 || scid > max_service_context_id ) {
4822 decode_UnknownServiceContext(tvb, tree, offset, stream_is_be, boundary);
4826 temp_offset = *offset;
4827 /* get sequence length, new endianness and boundary for encapsulation */
4828 context_data_len = get_CDR_encap_info(tvb, sub_tree1, offset,
4829 stream_is_be, boundary,
4830 &encapsulation_is_be , &encapsulation_boundary);
4833 tf_st1 = proto_tree_add_text (tree, tvb, temp_offset, sizeof(context_data_len) + context_data_len , service_context_name);
4834 sub_tree1 = proto_item_add_subtree (tf_st1, ett_giop_scl_st1);
4837 if (context_data_len == 0)
4840 /* See CORBA 3.0.2 standard, section Section 15.3.3 "Encapsulation",
4841 * for how CDR types can be marshalled into a sequence<octet>.
4842 * The first octet in the sequence determines endian order,
4843 * 0 == big-endian, 1 == little-endian
4848 case 0x01: /* Codesets */
4849 decode_CodeSets(tvb, sub_tree1, offset,
4850 encapsulation_is_be, encapsulation_boundary);
4852 case 0x0a: /* RTCorbaPriority */
4853 decode_RTCorbaPriority(tvb, sub_tree1, offset,
4854 encapsulation_is_be, encapsulation_boundary);
4858 /* Need to fill these in as we learn them */
4859 *offset = temp_offset1;
4860 decode_UnknownServiceContext(tvb, sub_tree1, offset, stream_is_be,
4864 /* Set the offset to the end of the context_data sequence */
4865 *offset = temp_offset1 + sizeof(context_data_len) + context_data_len;
4870 proto_item_set_len(tf, *offset - start_offset);
4874 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
4877 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
4878 gboolean stream_is_big_endian,
4881 guint32 length; /* string length */
4882 guint32 minor_code_value;
4883 guint32 completion_status;
4885 gchar *buf; /* pointer to string buffer */
4887 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
4890 proto_tree_add_text(tree, tvb, *offset-4, 4,
4891 "Exception length: %u", length);
4893 proto_tree_add_text(tree, tvb, *offset - length, length,
4894 "Exception id: %s", buf );
4899 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4900 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4903 proto_tree_add_text(tree, tvb, *offset-8, 4,
4904 "Minor code value: %u", minor_code_value);
4905 proto_tree_add_text(tree, tvb, *offset-4, 4,
4906 "Completion Status: %u", completion_status);
4912 * Helper functions for dissecting TypeCodes
4914 * These functions decode the complex parameter lists
4915 * of TypeCodes as defined in the CORBA spec chapter 15.
4918 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4919 gboolean stream_is_big_endian, guint32 boundary) {
4921 guint32 new_boundary; /* new boundary for encapsulation */
4922 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4924 guint32 seqlen; /* sequence length */
4926 /* get sequence length, new endianness and boundary for encapsulation */
4927 seqlen = get_CDR_encap_info(tvb, tree, offset,
4928 stream_is_big_endian, boundary,
4929 &new_stream_is_big_endian, &new_boundary);
4931 /* get repository ID */
4932 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4936 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4937 hf_giop_typecode_name);
4942 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4943 gboolean stream_is_big_endian, guint32 boundary,
4944 MessageHeader * header ) {
4946 guint32 new_boundary; /* new boundary for encapsulation */
4947 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4949 guint32 count; /* parameter count (of tuples) */
4950 guint32 seqlen; /* sequence length */
4951 guint32 i; /* loop index */
4953 /* get sequence lengt,h new endianness and boundary for encapsulation */
4954 seqlen = get_CDR_encap_info(tvb, tree, offset,
4955 stream_is_big_endian, boundary,
4956 &new_stream_is_big_endian, &new_boundary);
4958 /* get repository ID */
4959 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4963 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4964 hf_giop_typecode_name);
4966 /* get count of tuples */
4967 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4969 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4970 *offset-sizeof(count),4,count);
4973 /* get all tuples */
4974 for (i=0; i< count; i++) {
4975 /* get member name */
4976 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4977 hf_giop_typecode_member_name);
4979 /* get member type */
4980 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4986 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4987 gboolean stream_is_big_endian, guint32 boundary,
4988 MessageHeader * header) {
4990 guint32 new_boundary; /* new boundary for encapsulation */
4991 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4993 guint32 TCKind; /* TypeCode */
4994 gint32 s_octet4; /* signed int32 */
4996 guint32 count; /* parameter count (of tuples) */
4997 guint32 seqlen; /* sequence length */
4998 guint32 i; /* loop index */
5000 /* get sequence legnth, 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 repository ID */
5006 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5010 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5011 hf_giop_typecode_name);
5013 /* get discriminant type */
5014 TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5016 /* get default used */
5017 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
5019 proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
5020 *offset-sizeof(s_octet4),4,s_octet4);
5022 /* get count of tuples */
5023 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5025 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5026 *offset-sizeof(count),4,count);
5029 /* get all tuples */
5030 for (i=0; i< count; i++) {
5031 /* get label value, based on TCKind above */
5032 dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
5034 /* get member name */
5035 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5036 hf_giop_typecode_member_name);
5038 /* get member type */
5039 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5045 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5046 gboolean stream_is_big_endian, guint32 boundary) {
5048 guint32 new_boundary; /* new boundary for encapsulation */
5049 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5051 guint32 count; /* parameter count (of tuples) */
5052 guint32 seqlen; /* sequence length */
5053 guint32 i; /* loop index */
5055 /* get sequence length, new endianness and boundary for encapsulation */
5056 seqlen = get_CDR_encap_info(tvb, tree, offset,
5057 stream_is_big_endian, boundary,
5058 &new_stream_is_big_endian, &new_boundary);
5060 /* get repository ID */
5061 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5065 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5066 hf_giop_typecode_name);
5068 /* get count of tuples */
5069 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5071 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5072 *offset-sizeof(count),4,count);
5075 /* get all tuples */
5076 for (i=0; i< count; i++) {
5077 /* get member name */
5078 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5079 hf_giop_typecode_member_name);
5085 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5086 gboolean stream_is_big_endian, guint32 boundary,
5087 MessageHeader * header) {
5089 guint32 new_boundary; /* new boundary for encapsulation */
5090 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5092 guint32 u_octet4; /* unsigned int32 */
5094 guint32 seqlen; /* sequence length */
5096 /* get sequence length, new endianness and boundary for encapsulation */
5097 seqlen = get_CDR_encap_info(tvb, tree, offset,
5098 stream_is_big_endian, boundary,
5099 &new_stream_is_big_endian, &new_boundary);
5101 /* get element type */
5102 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5104 /* get max length */
5105 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5107 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
5108 *offset-sizeof(u_octet4),4,u_octet4);
5113 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5114 gboolean stream_is_big_endian, guint32 boundary,
5115 MessageHeader * header) {
5117 guint32 new_boundary; /* new boundary for encapsulation */
5118 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5120 guint32 u_octet4; /* unsigned int32 */
5122 guint32 seqlen; /* sequence length */
5124 /* get sequence length, new endianness and boundary for encapsulation */
5125 seqlen = get_CDR_encap_info(tvb, tree, offset,
5126 stream_is_big_endian, boundary,
5127 &new_stream_is_big_endian, &new_boundary);
5129 /* get element type */
5130 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5133 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5135 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5136 *offset-sizeof(u_octet4),4,u_octet4);
5141 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5142 gboolean stream_is_big_endian, guint32 boundary,
5143 MessageHeader * header) {
5145 guint32 new_boundary; /* new boundary for encapsulation */
5146 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5148 guint32 seqlen; /* sequence length */
5150 /* get sequence legnth, new endianness and boundary for encapsulation */
5151 seqlen = get_CDR_encap_info(tvb, tree, offset,
5152 stream_is_big_endian, boundary,
5153 &new_stream_is_big_endian, &new_boundary);
5155 /* get repository ID */
5156 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5160 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5161 hf_giop_typecode_name);
5163 /* get ??? (noname) TypeCode */
5164 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5169 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5170 gboolean stream_is_big_endian, guint32 boundary,
5171 MessageHeader * header) {
5173 guint32 new_boundary; /* new boundary for encapsulation */
5174 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5176 guint32 count; /* parameter count (of tuples) */
5177 guint32 seqlen; /* sequence length */
5178 guint32 i; /* loop index */
5180 /* get sequence length, new endianness and boundary for encapsulation */
5181 seqlen = get_CDR_encap_info(tvb, tree, offset,
5182 stream_is_big_endian, boundary,
5183 &new_stream_is_big_endian, &new_boundary);
5185 /* get repository ID */
5186 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5190 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5191 hf_giop_typecode_name);
5193 /* get count of tuples */
5194 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5196 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5197 *offset-sizeof(count),4,count);
5200 /* get all tuples */
5201 for (i=0; i< count; i++) {
5202 /* get member name */
5203 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5204 hf_giop_typecode_member_name);
5206 /* get member type */
5207 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5213 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5214 gboolean stream_is_big_endian, guint32 boundary,
5215 MessageHeader * header) {
5217 guint32 new_boundary; /* new boundary for encapsulation */
5218 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5220 gint16 s_octet2; /* signed int16 */
5222 guint32 count; /* parameter count (of tuples) */
5223 guint32 seqlen; /* sequence length */
5224 guint32 i; /* loop index */
5226 /* get sequence length, new endianness and boundary for encapsulation */
5227 seqlen = get_CDR_encap_info(tvb, tree, offset,
5228 stream_is_big_endian, boundary,
5229 &new_stream_is_big_endian, &new_boundary);
5231 /* get repository ID */
5232 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5236 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5237 hf_giop_typecode_name);
5239 /* get ValueModifier */
5240 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5242 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5243 *offset-sizeof(s_octet2),2,s_octet2);
5246 /* get conrete base */
5247 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5249 /* get count of tuples */
5250 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5252 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5253 *offset-sizeof(count),4,count);
5256 /* get all tuples */
5257 for (i=0; i< count; i++) {
5258 /* get member name */
5259 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5260 hf_giop_typecode_member_name);
5262 /* get member type */
5263 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5265 /* get Visibility */
5266 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5268 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5269 *offset-sizeof(s_octet2),2,s_octet2);
5276 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5277 gboolean stream_is_big_endian, guint32 boundary,
5278 MessageHeader * header) {
5280 guint32 new_boundary; /* new boundary for encapsulation */
5281 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5283 guint32 seqlen; /* sequence length */
5285 /* get sequence length, new endianness and boundary for encapsulation */
5286 seqlen = get_CDR_encap_info(tvb, tree, offset,
5287 stream_is_big_endian, boundary,
5288 &new_stream_is_big_endian, &new_boundary);
5290 /* get repository ID */
5291 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5295 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5296 hf_giop_typecode_name);
5298 /* get ??? (noname) TypeCode */
5299 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5303 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5304 gboolean stream_is_big_endian, guint32 boundary) {
5306 guint32 new_boundary; /* new boundary for encapsulation */
5307 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5309 guint32 seqlen; /* sequence length */
5311 /* get sequence length, new endianness and boundary for encapsulation */
5312 seqlen = get_CDR_encap_info(tvb, tree, offset,
5313 stream_is_big_endian, boundary,
5314 &new_stream_is_big_endian, &new_boundary);
5316 /* get repository ID */
5317 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5321 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5322 hf_giop_typecode_name);
5327 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5328 gboolean stream_is_big_endian, guint32 boundary) {
5330 guint32 new_boundary; /* new boundary for encapsulation */
5331 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5333 guint32 seqlen; /* sequence length */
5335 /* get sequence length, new endianness and boundary for encapsulation */
5336 seqlen = get_CDR_encap_info(tvb, tree, offset,
5337 stream_is_big_endian, boundary,
5338 &new_stream_is_big_endian, &new_boundary);
5340 /* get repository ID */
5341 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5345 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5346 hf_giop_typecode_name);
5350 /* Typecode parameter lists are encoded as encapsulations and
5351 * this function gets the encapsulation information; see
5352 * CORBA spec chapter 15
5355 * Renamed to get_CDR_encap_info() for any encapsulation
5356 * we come across, useful helper function
5358 * Also, should return immediately if seqlen == 0.
5359 * ie: Forget about trying to grab endianess for
5360 * zero length sequence.
5362 * Caller must always check seqlen == 0, and not assume its value
5365 * Note: there seemed to be considerable confusion in corba
5366 * circles as to the correct interpretation of encapsulations,
5367 * and zero length sequences etc, but this is our best bet at the
5374 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5375 gboolean old_stream_is_big_endian, guint32 old_boundary,
5376 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5378 guint32 seqlen; /* sequence length */
5379 guint8 giop_endianess;
5381 /* Get sequence length of parameter list */
5382 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5384 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5385 *offset-sizeof(seqlen),4,seqlen);
5391 * seqlen == 0, implies no endianess and no data
5392 * so just return. Populate new_boundary_ptr and
5393 * new_stream_is_big_endian_ptr with current (old)
5394 * values, just to keep everyone happy. -- FS
5400 *new_boundary_ptr = old_boundary;
5401 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5407 /* Start of encapsulation of parameter list */
5408 *new_boundary_ptr = *offset; /* remember */
5409 giop_endianess = get_CDR_octet(tvb,offset);
5411 *new_stream_is_big_endian_ptr = ! giop_endianess;
5414 * Glib: typedef gint gboolean;
5415 * ie: It is not a guint8, so cannot use sizeof to correctly
5421 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5422 *offset-1,1,giop_endianess);
5432 * gets a TypeCode complex string parameter and
5433 * displays it in the relevant tree.
5436 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5437 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5439 guint32 u_octet4; /* unsigned int32 */
5440 gchar *buf; /* ptr to string buffer */
5443 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5446 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5447 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5449 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5453 g_free(buf); /* dont forget */
5458 * For a given data type, given by a TypeCode gets the associated data
5459 * and displays it in the relevant tree.
5462 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5463 gboolean stream_is_big_endian, guint32 boundary,
5464 MessageHeader * header, guint32 data_type ) {
5466 gboolean my_boolean; /* boolean */
5468 gint8 s_octet1; /* signed int8 */
5469 guint8 u_octet1; /* unsigned int8 */
5471 gint16 s_octet2; /* signed int16 */
5472 guint16 u_octet2; /* unsigned int16 */
5474 gint32 s_octet4; /* signed int32 */
5475 guint32 u_octet4; /* unsigned int32 */
5477 gdouble my_double; /* double */
5478 gfloat my_float; /* float */
5480 gchar *buf = NULL; /* ptr to string buffer */
5482 /* Grab the data according to data type */
5484 switch (data_type) {
5486 /* nothing to decode */
5489 /* nothing to decode */
5492 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5494 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5495 *offset-sizeof(s_octet2),2,s_octet2);
5499 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5501 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5502 *offset-sizeof(s_octet4),4,s_octet4);
5506 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5508 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5509 *offset-sizeof(u_octet2),2,u_octet2);
5513 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5515 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5516 *offset-sizeof(u_octet4),4,u_octet4);
5520 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5522 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5523 *offset-sizeof(my_float),4,my_float);
5527 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5529 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5530 *offset-sizeof(my_double),8,my_double);
5534 my_boolean = get_CDR_boolean(tvb,offset);
5536 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5537 *offset-1,1,my_boolean);
5541 u_octet1 = get_CDR_char(tvb,offset);
5543 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5544 *offset-sizeof(u_octet1),1,u_octet1);
5548 u_octet1 = get_CDR_octet(tvb,offset);
5550 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5551 *offset-sizeof(u_octet1),1,u_octet1);
5555 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5558 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5569 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5571 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5572 *offset-sizeof(u_octet4),4,u_octet4);
5576 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5578 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5579 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5581 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5582 *offset-u_octet4,u_octet4,buf);
5586 g_free(buf); /* dont forget */
5603 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5606 * XXX - can any of these throw an exception?
5607 * If so, we need to catch the exception and free "buf".
5609 if (s_octet1 < 0) { /* no size to add to tree */
5610 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5611 *offset+s_octet1,(-s_octet1),buf);
5613 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5614 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5615 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5616 *offset-s_octet1,s_octet1,buf);
5620 g_free(buf); /* dont forget */
5623 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5626 * XXX - can any of these throw an exception?
5627 * If so, we need to catch the exception and free "buf".
5629 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5630 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5631 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5632 *offset-u_octet4,u_octet4,buf);
5635 g_free(buf); /* dont forget */
5645 case tk_abstract_interface:
5648 g_warning("giop: Unknown typecode data type %u \n", data_type);