2 * Routines for CORBA GIOP/IIOP packet disassembly
5 * Laurent Deniel <deniel@worldnet.fr>
6 * Craig Rodrigues <rodrigc@mediaone.net>
8 * GIOP API extensions by,
9 * Frank Singleton <frank.singleton@ericsson.com>
10 * Trevor Shepherd <eustrsd@am1.ericsson.se>
12 * $Id: packet-giop.c,v 1.42 2001/07/05 20:54:56 guy Exp $
14 * Ethereal - Network traffic analyzer
15 * By Gerald Combs <gerald@ethereal.com>
16 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 * 1. heuristic giop dissector table [started]
39 * 2. GUI options, see 20
40 * 3. Remove unneccessary reply_status in heuristic dissector calls (now
41 * part of MessageHeader) [done]
42 * 4. get_CDR_xxx should be passed an alignment offset value
43 * rather than GIOP_HEADER_SIZE, as alignment can also change in a
44 * octet stream when eg: encapsulation is used [done]
45 * 5. GIOP users should eventually get there own tvbuff, and
46 * not rely on the GIOP tvbuff, more robust
47 * 6. get_CDR_string,wchar,wstring etc should handle different
48 * GIOP versions [started]
49 * 7. Fix situation where req_id is not unique in a logfile [done, use FN/MFN, needs improving.]
51 * 8. Keep request_1_2 in step with request_1_1 [started]
52 * 9. Explicit module name dissection [done]
53 * 10. Decode IOR and put in a useful struct [IOR decode started]
54 * 11. Fix encapsulation of IOR etc and boundary [done]
55 * 12. handle get_CDR_typeCode() [started]
56 * 13. Handle different IOR profiles
57 * 14. Change printable_string to RETURN a new string, not to modify the old.
58 * or, new function, make_printable_string [done, make_printable_string]
60 * 15. Handle "TCKind", and forget about eg: enum translation to symbolic values
61 * otherwise need knowledge of sub dissectors data - YUK [done]
62 * 16. Handle multiple RepoId representations, besides IDL:Echo:1.0 (see 13.)
63 * 17. Pass subset of RepoID to explicit dissector.
64 * eg : If IDL:Mod1/Mod2/Int3:1.0 then pass "Mod1/Mode2/Int3" to sub dissector[done]
65 * 18. Better hashing algorithms
66 * 19. Handle hash collision properly .
67 * 20. Allow users to paste a stringified IOR into the GUI, and tie it
69 * 21. Add complete_request_packet_list and complete_reply_packet_hash.[done]
70 * 22. Handle case where users click in any order, AND try and match
71 * REPLY msg to the correct REQUEST msg when we have a request_id collision.[done]
72 * 23. Clean up memory management for all those g_malloc's etc
73 * 24. register_giop_user_module could return a key for every distinct Module/Interface
74 * the sub_dissector uses. So, instead of strcmp()'s when handling the
75 * namespace of an operation, we could have a lookup table instead.
76 * 25. A few typedefs in the right place.
77 * 26 Improve handling of gchar * and use const gchar * where possible.
78 * 27. Read/write IOR etc to/from file, allows objkey hash to be built from
79 * external data [read done, write incomplete]
80 * 28. Call sub dissector only if tvb_offset_exists(). [Done, this is checked
81 * inside try_explicit_giop_dissector() ]
83 * 29. Make add/delete routine for objkey hash as it may be useful when say reading
84 * stringified IOR's from a file to add them to our hash. ie: There are other ways
85 * to populate our object key hash besides REPLY's to RESOLVE(request) [done]
87 * 30. Add routine to encode/decode stringified IOR's [decode done]
88 * 31. Add routine to read IOR's from file [done]
89 * 32. TypeCode -none-, needs decoding.
90 * 33. Complete dissect_data_for_typecode.
91 * 34. For complex TypeCodes need to check final offset against original offset + sequence length.
92 * 35. Update REQUEST/REPLY 1_2 according to IDL (eg; ServiceContextList etc).
93 * 36. Adding decode_ServiceContextList, incomplete.
94 * 37. Helper functions should not ALWAYS rely on header to find current endianess. It should
95 * be passed from user, eg Use stream_is_big_endian. [started]
96 * 38. Remove unwanted/unused function parameters, see decode_IOR [started]
97 * 40. Add sequence <IOP::TaggedComponent> components to IIOP IOR profile. Perhaps
98 * decode_IOP_TaggedComponents as a helper function. [done - NOT helper]
100 * 41. Make important field searchable from Message header. ie: Remove add_text_
101 * 42. Use sub-tree for decode_ServiceContextList, looks better.
102 * 43. dissect_reply_body, no exception dissector calls
103 * - call subdiss directly, as we already have handle.
104 * - add repoid to heuristic call also.
106 * 44. typedef using xxx_t in .h file.
107 * 45. Subdissectors should not be passed MessageHeader to find endianness and
108 * version, they should be passed directly ?
109 * 46. get_CDR_wchar and wstring need wide chars decoded (just dumped in
110 * any readable form at present, not handled well at all, suggestions welcome -- FS
111 * 47. Change ...add_text to ...add_xxx (ie use hf fields).
113 * 48. BUG - file load with a GIOP filter set, causes the FN/MFN data struct to be
114 * not initiated properly. Hit "Reload" as a workaround, til I fix this -- FS
121 * Intended Decode strategy:
122 * =========================
126 * REQUEST: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
127 * and populate complete_request_packet_hash
129 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
134 * REQUEST: FN -> giop_sub_handle_t directly (via complete_request_packet_hash)
136 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
137 * (via complete_request_packet_hash
143 * 1. Request_ID's are unique only per connection.
145 * 2. You must be monitoring the network when the client does
146 * a REQUEST(resolve), otherwise I have no knowledge of the
147 * association between object_key and REPOID. I could talk to
148 * a Nameserver, but then I would start "generating" packets.
149 * This is probably not a good thing for a protocol analyser.
150 * Also, how could I decode logfiles offline.
152 * TODO -- Read stringified IORs from an input file.[done]
154 * 3. User clicks (REQUEST) is currently handle the same as
155 * the initial pass handling.
157 * ie: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
162 * Important Data Structures:
167 * This is a hash table that maps IDL Module/Interface Names (Key)
168 * to sub_dissector handles, giop_sub_handle_t. It is populated
169 * by subdissectors, via register_giop_user_module(). This
170 * table is used when we have a REPOID, and explicitly wish to
171 * call the subdissector that has registered responsibility for
172 * that IDL module/interface.
178 * This singly linked list is used to hold entries for
179 * heuristic based subdissectors. It is populated by sub_dissectors
180 * wishing to be called via heuristic mechanisms. They do this
181 * via the register_giop_user() function.
187 * This hash table maps object_key's (key) onto REPOID's (val).
188 * Once a client has REQUEST(resolve) an object , it knows about
189 * an object (interface) via its object_key (see IOR). So in order to follow
190 * packets that contain an object_key only, and to be able to forward it
191 * to the correct explicit subdissector, we need this table.
193 * So, I listen in on REQUEST(resolve) messages between client and
194 * Nameserver, and store the respones (REPLY/Objkey,Repo_ID) here.
196 * Also, stringified IOR's can be read from a file "IOR.txt" and used
197 * to populate this hash also.
200 * Other Data structures
201 * =======================
203 * These structures have been added to minimise the possibility
204 * of incorrectly interpreted packets when people click all
205 * over the place, in no particular order, when the request_id's are
206 * not unique as captured. If all request_is'd are unique, as captured, then
207 * we would not have to deal with this problem.
210 * When the logfile or packets are initially being processed, I will
211 * build 2 structures. The intent is to be able to map a REPLY message
212 * back to the most recent REQUEST message with the same Request_ID
213 * (TODO and matching port and IP address ??)
219 * MFN - Matching Frame Number
222 * complete_request_packet_list
223 * ----------------------------
225 * This is a list that contains ALL the FN's that are REQUEST's, along with
226 * operation,request_id and giop_sub_handle_t
228 * complete_reply_packet_hash
229 * --------------------------
231 * This is a hash table. It is populated with FN (key) and MFN (val).
232 * This allows me to handle the case, where if you click on any REPLY
233 * message, I can lookup the matching request. This can improve
234 * the match rate between REQUEST and REPLY when people click in
235 * any old fashion, but is NOT foolproof.
237 * The algorithm I use to populate this hash during initial pass,
240 * If packet is a REPLY, note the reqid, and then traverse backwards
241 * through the complete_request_packet_list from its tail, looking
242 * for a FN that has the same Request_id. Once found, take the found FN
243 * from complete_reply_packet_hash, and insert it into the MFN field
244 * of the complete_reply_packet_hash.
247 * See TODO for improvements to above algorithm.
249 * So now when people click on a REQUEST packet, I can call lookup the
250 * giop_sub_handle_t directly from complete_request_packet_list.
252 * And, when they click on a REPLY, I grab the MFN of this FN from
253 * complete_reply_packet_hash, then look that up in the complete_request_packet_list
254 * and call the sub_dissector directly.
256 * So, how do I differentiate between the initial processing of incoming
257 * packets, and a user clickin on one ? Good question.
259 * I leverage the pinfo_fd->flags.visited on a per frame
262 * To quote from the ever helpful development list
264 * " When a capture file is initially loaded, all "visited" flags
265 * are 0. Ethereal then makes the first pass through file,
266 * sequentially dissecting each packet. After the packet is
267 * dissected the first time, "visited" is 1. (See the end of
268 * dissect_packet() in epan/packet.c; that's the code that
269 * sets "visited" to 1).
271 * By the time a user clicks on a packet, "visited" will already
272 * be 1 because Ethereal will have already done its first pass
273 * through the packets.
275 * Reload acts just like a normal Close/Open, except that it
276 * doesn't need to ask for a filename. So yes, the reload button
277 * clears the flags and re-dissects the file, just as if the file
278 * had been "opened". "
287 #ifdef HAVE_SYS_TYPES_H
288 # include <sys/types.h>
297 #ifdef NEED_STRERROR_H
298 #include "strerror.h"
302 #include "packet-giop.h"
305 * This affects how we handle context_data inside ServiceContext structs.
306 * According to CORBA 2.4.2, Context data is encapsulated in octet sequences,
307 * but so far I haven't seen the that on the wire. But, maybe its me -- FS
311 #define CONTEXT_DATA_IS_ENCAPSULATED 0
315 * Set to 1 for DEBUG output - TODO make this a runtime option
323 * ------------------------------------------------------------------------------------------+
324 * Private Helper function Declarations
325 * ------------------------------------------------------------------------------------------+
329 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
330 guint32 boundary, gboolean new_endianess, gchar *repobuf,
331 gboolean store_flag);
333 static void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
334 gboolean stream_is_be, guint32 boundary);
336 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
337 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf);
339 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
340 guint32 boundary, gboolean stream_is_big_endian );
342 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
343 gboolean stream_is_big_endian,
346 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
347 gboolean stream_is_big_endian, guint32 boundary,
348 MessageHeader * header);
350 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
351 gboolean stream_is_big_endian, guint32 boundary,
352 MessageHeader * header);
354 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
355 gboolean stream_is_big_endian, guint32 boundary,
356 MessageHeader * header );
358 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
359 gboolean stream_is_big_endian, guint32 boundary,
360 MessageHeader * header);
362 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
363 gboolean stream_is_big_endian, guint32 boundary,
364 MessageHeader * header);
366 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
367 gboolean stream_is_big_endian, guint32 boundary,
368 MessageHeader * header);
370 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
371 gboolean stream_is_big_endian, guint32 boundary,
372 MessageHeader * header);
374 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
375 gboolean stream_is_big_endian, guint32 boundary,
376 MessageHeader * header);
378 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
379 gboolean stream_is_big_endian, guint32 boundary,
380 MessageHeader * header);
382 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
383 gboolean stream_is_big_endian, guint32 boundary,
384 MessageHeader * header);
386 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
387 gboolean stream_is_big_endian, guint32 boundary,
388 MessageHeader * header);
390 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
391 gboolean stream_is_big_endian, guint32 boundary,
392 MessageHeader * header);
395 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
396 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
398 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
399 gboolean stream_is_big_endian, guint32 boundary,
400 MessageHeader * header, guint32 data_type );
406 * ------------------------------------------------------------------------------------------+
407 * Data/Variables/Structs
408 * ------------------------------------------------------------------------------------------+
412 static int proto_giop = -1;
413 static int hf_giop_message_type = -1;
414 static int hf_giop_message_size = -1;
415 static int hf_giop_repoid = -1;
416 static int hf_giop_string_length = -1;
417 static int hf_giop_sequence_length = -1;
418 static int hf_giop_profile_id = -1;
419 static int hf_giop_type_id = -1;
420 static int hf_giop_iiop_v_maj = -1;
421 static int hf_giop_iiop_v_min = -1;
422 static int hf_giop_endianess = -1; /* esp encapsulations */
423 static int hf_giop_IOR_tag = -1;
424 static int hf_giop_IIOP_tag = -1;
426 static int hf_giop_TCKind = -1;
427 static int hf_giop_typecode_count = -1;
428 static int hf_giop_typecode_default_used = -1;
429 static int hf_giop_typecode_digits = -1;
430 static int hf_giop_typecode_length = -1;
431 static int hf_giop_typecode_max_length = -1;
432 static int hf_giop_typecode_member_name = -1;
433 static int hf_giop_typecode_name = -1;
434 static int hf_giop_typecode_scale = -1;
435 static int hf_giop_typecode_ValueModifier = -1;
436 static int hf_giop_typecode_Visibility = -1;
438 static int hf_giop_type_boolean = -1;
439 static int hf_giop_type_char = -1;
440 static int hf_giop_type_double = -1;
441 static int hf_giop_type_enum = -1;
442 static int hf_giop_type_float = -1;
443 static int hf_giop_type_long = -1;
444 static int hf_giop_type_octet = -1;
445 static int hf_giop_type_short = -1;
446 static int hf_giop_type_string = -1;
447 static int hf_giop_type_ulong = -1;
448 static int hf_giop_type_ushort = -1;
450 static int hf_giop_iiop_host = -1;
451 static int hf_giop_iiop_port = -1;
452 static int hf_giop_iop_vscid = -1;
453 static int hf_giop_iop_scid = -1;
459 static gint ett_giop = -1;
460 static gint ett_giop_reply = -1;
461 static gint ett_giop_request = -1;
462 static gint ett_giop_cancel_request = -1;
463 static gint ett_giop_locate_request = -1;
464 static gint ett_giop_locate_reply = -1;
465 static gint ett_giop_fragment = -1;
467 static gint ett_giop_scl = -1; /* ServiceContextList */
468 static gint ett_giop_ior = -1; /* IOR */
473 static const value_string giop_endianess_vals[] = {
474 { 0x0, "Big Endian" },
475 { 0x1, "Little Endian" },
479 static const value_string sync_scope[] = {
480 { 0x0, "SYNC_NONE" },
481 { 0x1, "SYNC_WITH_TRANSPORT"},
482 { 0x2, "SYNC_WITH_SERVER"},
483 { 0x3, "SYNC_WITH_TARGET"},
489 static const value_string profile_id_vals[] = {
490 { 0x0, "TAG_INTERNET_IOP" },
491 { 0x1, "TAG_MULTIPLE_COMPONENTS"},
492 { 0x2, "TAG_SCCP_IOP"},
496 static const value_string giop_message_types[] = {
499 { 0x2, "CancelRequest"},
500 { 0x3, "LocateRequest"},
501 { 0x4, "LocateReply"},
502 { 0x5, "CloseConnection"},
503 { 0x6, "MessageError"},
508 static const value_string giop_locate_status_types[] = {
509 { 0x0, "Unknown Object" },
510 { 0x1, "Object Here"},
511 { 0x2, "Object Forward"},
512 { 0x3, "Object Forward Perm"},
513 { 0x4, "Loc System Exception"},
514 { 0x5, "Loc Needs Addressing Mode"},
518 static const value_string tckind_vals[] = {
531 { 12, "tk_TypeCode"},
532 { 13, "tk_Principal"},
538 { 19, "tk_sequence"},
542 { 23, "tk_longlong"},
543 { 24, "tk_ulonglong"},
544 { 25, "tk_longdouble"},
549 { 30, "tk_value_box"},
551 { 32, "tk_abstract_interface"},
557 #define GIOP_MAGIC "GIOP"
560 * TAGS for IOR Profiles
562 * Chapter 13 Corba 2.4.2
566 #define IOP_TAG_INTERNET_IOP 0
567 #define IOP_TAG_MULTIPLE_COMPONENTS 1
570 /* Max Supported versions */
572 static const guint GIOP_MAJOR = 1;
573 static const guint GIOP_MINOR = 2;
576 static const int KeyAddr = 0;
577 static const int ProfileAddr = 1;
578 static const int ReferenceAddr = 2;
582 static const value_string reply_status_types[] = {
583 { NO_EXCEPTION, "No Exception" } ,
584 { USER_EXCEPTION, "User Exception" } ,
585 { SYSTEM_EXCEPTION, "System Exception" } ,
586 { LOCATION_FORWARD, "Location Forward" } ,
587 { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
588 { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
594 typedef enum LocateStatusType
599 OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
600 LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
601 LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
605 typedef struct LocateReplyHeader
608 guint32 locate_status;
614 * DATA - complete_request_list
617 static GList *giop_complete_request_list;
619 struct comp_req_list_entry {
620 guint32 fn; /* frame number */
621 gchar * operation; /* echo echoString */
622 giop_sub_handle_t *subh; /* handle to sub dissector */
623 guint32 reqid; /* request id */
624 gchar * repoid; /* repository ID */
627 typedef struct comp_req_list_entry comp_req_list_entry_t;
631 * DATA - complete_reply_hash
633 * Maps reply FN to request MFN
636 static int complete_reply_hash_count = 1000; /* storage size for our permanent data */
637 /* ie: 1000 entries -- needs tweaking -- FS */
639 struct complete_reply_hash_key {
640 guint32 fn; /* reply frame number */
643 struct complete_reply_hash_val {
644 guint32 mfn; /* matching frame number (request) */
647 GHashTable *giop_complete_reply_hash = NULL; /* hash */
648 GMemChunk *giop_complete_reply_keys = NULL; /* key storage */
649 GMemChunk *giop_complete_reply_vals = NULL; /* val storage */
653 * DATA - Module Hash stuff to store data from register_giop_user_module
655 * ie: module (or interface ?) name, and ptr to sub_dissector handle
657 * With this knowledge, we can call a sub dissector directly,
660 * objkey -> repoid -> sub_dissector via registered module/interface
665 static int giop_module_init_count = 100; /* storage size for our permanent data */
666 /* ie: 100 entries -- needs tweaking -- FS */
668 struct giop_module_key {
669 gchar *module; /* module (interface?) name */
672 struct giop_module_val {
673 giop_sub_handle_t *subh; /* handle to sub dissector */
676 GHashTable *giop_module_hash = NULL; /* hash */
677 GMemChunk *giop_module_keys = NULL; /* key storage */
678 GMemChunk *giop_module_vals = NULL; /* val storage */
682 * DATA - GSList to store list of function (dissector) pointers.
683 * for heuristic dissection.
687 static GSList *giop_sub_list = NULL;
690 * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
691 * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
693 * With this knowledge, we can call a sub dissector directly later
696 * objkey -> repoid -> sub_dissector via registered module/interface
698 * rather than heuristic calls that do not provide operation context.
699 * (unless we pass the RepoID for a given objkey -- hmmm)
704 * Interesting operation list, add more if you want to save
708 static const char giop_op_resolve[] = "resolve";
709 static const char giop_op_bind_new_context[] = "bind_new_context";
710 static const char giop_op_bind[] = "bind";
713 * Enums for interesting local operations, that we may need to monitor
714 * with their subsequent replies
719 request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
720 request_bind_new_context_op_val, /* bind_new_context */
721 request_bind_op_val, /* bind */
722 request_get_INIT_op_val, /* finding Nameserver */
728 * hash for mapping object keys onto object namespaces, so
729 * I can call the correct dissector.
735 * Where did I get the IOR from.
739 req_res = 0, /* REQUEST (resolve) */
740 file, /* stringified IOR' in a file */
744 typedef enum ior_src ior_src_t;
749 * Enums for my lists and hash's
752 enum collection_data {
753 cd_heuristic_users = 0,
756 cd_complete_request_list,
757 cd_complete_reply_hash
760 typedef enum collection_data collection_data_t;
764 static int giop_objkey_init_count = 100; /* storage size for our permanent data */
765 /* ie: 100 entries -- needs tweaking -- FS */
767 struct giop_object_key {
768 guint8 *objkey; /* ptr to object key */
769 guint32 objkey_len; /* length */
772 struct giop_object_val {
773 guint8 *repo_id; /* ptr to Repository ID string */
774 ior_src_t src; /* where did Iget this IOR from */
777 GHashTable *giop_objkey_hash = NULL; /* hash */
778 GMemChunk *giop_objkey_keys = NULL; /* key storage */
779 GMemChunk *giop_objkey_vals = NULL; /* val storage */
784 * ------------------------------------------------------------------------------------------+
785 * Private helper functions
786 * ------------------------------------------------------------------------------------------+
792 * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
795 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
796 GList * newlist_start;
797 comp_req_list_entry_t * entry = NULL;
800 entry = g_malloc(sizeof(comp_req_list_entry_t));
801 opn = g_strdup(op); /* duplicate operation for storage */
804 entry->reqid = reqid;
806 entry->operation = opn;
807 entry->repoid = NULL; /* dont have yet */
809 newlist_start = g_list_append (list, entry); /* append */
811 return newlist_start;
816 * Used to find an entry with matching Frame Number FN
817 * in the complete_request_list list.
820 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
822 GList * element; /* entry in list */
823 comp_req_list_entry_t * entry_ptr = NULL;
825 element = g_list_last(giop_complete_request_list); /* start from last */
827 while(element) { /* valid list entry */
828 entry_ptr = element->data; /* grab data pointer */
829 if (entry_ptr->fn == fn) { /* similar FN */
832 element = g_list_previous(element); /* try next previous */
835 return NULL; /* no match so return NULL */
840 * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
842 * Call this when you know a FN and matching giop_sub_handle_t and repoid
844 * This is done in say, try_explicit_dissector for example.
848 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
850 comp_req_list_entry_t * entry = NULL;
851 entry = find_fn_in_list(fn); /* grab FN data entry */
855 entry->repoid = g_strdup(repoid); /* copy and store */
863 /* giop_complete_reply_hash "EQUAL" Functions */
865 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
866 struct complete_reply_hash_key *mk1 = (struct complete_reply_hash_key *)v;
867 struct complete_reply_hash_key *mk2 = (struct complete_reply_hash_key *)w;
869 if (mk1->fn == mk2->fn) {
873 return 0; /* found differences */
876 /* giop_complete_reply_hash "HASH" Functions */
878 static guint32 complete_reply_hash_fn(gconstpointer v) {
879 guint32 val; /* init hash value */
880 struct complete_reply_hash_key *key = (struct complete_reply_hash_key *)v;
882 val = key->fn; /* simple and unique */
889 * Insert the FN and MFN together in our complete_reply_hash.
892 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
894 struct complete_reply_hash_key key, *new_key;
895 struct complete_reply_hash_val *val = NULL;
899 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
902 return; /* FN collision */
905 new_key = g_mem_chunk_alloc(giop_complete_reply_keys);
906 new_key->fn = fn; /* save FN */
908 val = g_mem_chunk_alloc(giop_complete_reply_vals);
909 val->mfn = mfn; /* and MFN */
911 g_hash_table_insert(giop_complete_reply_hash, new_key, val);
916 * Find the MFN values from a given FN key.
917 * Assumes the complete_reply_hash is already populated.
920 static guint32 get_mfn_from_fn(guint32 fn) {
922 struct complete_reply_hash_key key;
923 struct complete_reply_hash_val *val = NULL;
924 guint32 mfn = fn; /* save */
927 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
930 mfn = val->mfn; /* grab it */
933 return mfn; /* mfn or fn if not found */
938 * Attempt to find the MFN for this FN, and return it.
939 * Return MFN if found, or just FN if not. This is
940 * only used when we are building
943 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
945 GList * element; /* last entry in list */
946 comp_req_list_entry_t * entry_ptr = NULL;
948 /* Need Some pretty snappy code */
950 /* Loop back from current end of complete_request_list looking for */
951 /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
954 * As this routine is only called during initial pass of data,
955 * and NOT when a user clicks, it is ok to start from Current
956 * end of complete_request_list when searching for a match.
957 * As that list is bing populated in the same order as FN's
960 * Also, can make check for same reqid more detailed, but I start
961 * with reqid. Could add say port or address checks etc later ??
965 element = g_list_last(giop_complete_request_list); /* get last */
967 while(element) { /* valid list entry */
968 entry_ptr = element->data; /* grab data pointer */
969 if (entry_ptr->reqid == reqid) { /* similar reqid */
970 return entry_ptr->fn; /* return MFN */
972 element = g_list_previous(element); /* try next previous */
975 return fn; /* no match so return FN */
979 /* Module Hash "EQUAL" Functions */
981 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
982 struct giop_module_key *mk1 = (struct giop_module_key *)v;
983 struct giop_module_key *mk2 = (struct giop_module_key *)w;
985 if (!strcmp(mk1->module, mk2->module)) {
989 return 0; /* found differences */
992 /* Module Hash "HASH" Functions */
994 static guint32 giop_hash_module_hash(gconstpointer v) {
997 guint32 val = 0; /* init hash value */
999 struct giop_module_key *key = (struct giop_module_key *)v;
1002 * Hmm, try this simple hashing scheme for now.
1003 * ie: Simple summation, FIX later -- FS
1008 len = strlen(key->module);
1010 for (i=0; i<len; i++) {
1011 val += (guint8) key->module[i];
1020 * ------------------------------------------------------------------------------------------+
1021 * Public Utility functions
1022 * ------------------------------------------------------------------------------------------+
1029 * Routine to allow giop users to register their sub dissector function, name, and
1030 * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1031 * value returned from their proto_register_protocol(), so we can enable/disbale it
1032 * through the GUI (edit protocols).
1034 * This is used by try_explicit_giop_dissector() to find the
1035 * correct sub-dissector.
1039 void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
1041 struct giop_module_key module_key, *new_module_key;
1042 struct giop_module_val *module_val = NULL;
1044 module_key.module = module; /* module name */
1046 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1049 return; /* module name collision */
1052 /* So, passed module name should NOT exist in hash at this point.*/
1055 printf("giop:register_module: Adding Module %s to module hash \n", module);
1056 printf("giop:register_module: Module sub dissector name is %s \n", name);
1059 new_module_key = g_mem_chunk_alloc(giop_module_keys);
1060 new_module_key->module = module; /* save Module or interface name from IDL */
1062 module_val = g_mem_chunk_alloc(giop_module_vals);
1064 module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
1066 module_val->subh->sub_name = name; /* save dissector name */
1067 module_val->subh->sub_fn = sub; /* save subdissector*/
1068 module_val->subh->sub_proto = sub_proto; /* save subdissector's proto_XXX value */
1070 g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1077 /* Object Key Hash "EQUAL" Functions */
1079 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1080 struct giop_object_key *v1 = (struct giop_object_key *)v;
1081 struct giop_object_key *v2 = (struct giop_object_key *)w;
1083 if (v1->objkey_len != v2->objkey_len)
1084 return 0; /* no match because different length */
1086 /* Now do a byte comaprison */
1088 if (!memcmp(v1->objkey,v2->objkey, v1->objkey_len)) {
1089 return 1; /* compares ok */
1093 printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1096 return 0; /* found differences */
1099 /* Object Key Hash "HASH" Functions */
1101 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1102 struct giop_object_key *key = (struct giop_object_key *)v;
1105 guint32 val = 0; /* init hash value */
1109 * Hmm, try this simple hashing scheme for now.
1110 * ie: Simple summation
1116 printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1119 for (i=0; i< key->objkey_len; i++) {
1120 val += (guint8) key->objkey[i];
1128 * Routine to take an object key octet sequence, and length, and ptr to
1129 * a (null terminated )repository ID string, and store them in the obect key hash.
1131 * Blindly Inserts even if it does exist, See TODO at top for reason.
1134 static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
1136 struct giop_object_key objkey_key, *new_objkey_key;
1137 struct giop_object_val *objkey_val = NULL;
1139 objkey_key.objkey_len = len; /* length */
1140 objkey_key.objkey = obj; /* object key octet sequence */
1142 /* Look it up to see if it exists */
1144 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1146 /* CHANGED -- Same reqid, so abandon old entry */
1149 g_hash_table_remove(hash, &objkey_key);
1152 /* So, passed key should NOT exist in hash at this point.*/
1154 new_objkey_key = g_mem_chunk_alloc(giop_objkey_keys);
1155 new_objkey_key->objkey_len = len; /* save it */
1156 new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */
1158 objkey_val = g_mem_chunk_alloc(giop_objkey_vals);
1159 objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
1160 objkey_val->src = src; /* where IOR came from */
1164 printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
1165 objkey_val->repo_id, new_objkey_key->objkey_len);
1168 g_hash_table_insert(hash, new_objkey_key, objkey_val);
1175 * convert an ascii char representing a hex value,
1176 * to a numeric value.
1178 * returns value, or -1 if problem.
1182 static gint8 hex_char_to_val(guchar c){
1189 retval = c - 48; /* convert digit */
1193 c = toupper(c); /* convert to uppercase */
1194 if (c >= 'A' && c <= 'F') {
1205 * Convert from stringified IOR of the kind IOR:af4f7e459f....
1206 * to an IOR octet sequence.
1208 * User must free buffer.
1210 * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1211 * grab repoid etc for our objkey hash.
1215 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1218 gint8 tmpval; /* complete value */
1221 *out = g_new0(guint8, in_len); /* allocate buffer */
1227 /* skip past IOR: and convert character pairs to guint8 */
1229 for (i=4; i<in_len-1; i+=2) {
1230 if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1232 if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1233 g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1237 if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1238 g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1241 tmpval = tmpval_msb << 4;
1242 tmpval += tmpval_lsb;
1243 (*out)[(i-4)/2] = (guint8) tmpval;
1253 return (i-4)/2; /* length */
1260 * Simple getline, copied from somewhere :)
1264 static int getline(FILE *fp, gchar *line, int maxlen) {
1266 if (fgets(line,maxlen,fp) == NULL)
1269 return strlen(line);
1275 * Read a list of stringified IOR's from a named file, convert to IOR's
1276 * and store in object key hash
1279 static void read_IOR_strings_from_file(gchar *name, int max_iorlen) {
1280 guchar *buf = NULL; /* NOTE reused for every line */
1282 int ior_val_len; /* length after unstringifying. */
1284 guint8 *out = NULL; /* ptr to unstringified IOR */
1285 tvbuff_t *tvb = NULL; /* temp tvbuff for dissectin IORs */
1286 guint32 my_offset = 0;
1287 gboolean stream_is_big_endian;
1290 fp = fopen(name,"r"); /* open read only */
1293 if (errno == EACCES)
1294 fprintf(stderr, "Error opening file IOR.txt for reading: %s \n",strerror(errno));
1298 buf = g_malloc0(max_iorlen+1); /* input buf */
1300 while ((len = getline(fp,buf,max_iorlen+1)) > 0) {
1301 my_offset = 0; /* reset for every IOR read */
1303 ior_val_len = string_to_IOR(buf,len,&out); /* convert */
1307 /* Combination of tvb_new() and tvb_set_real_data(). Can throw ReportedBoundsError. */
1309 tvb = tvb_new_real_data(out,ior_val_len,ior_val_len, "GIOP FILE IOR");
1311 stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1312 decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1319 fclose(fp); /* be nice */
1328 * Init routine, setup our request hash stuff, or delete old ref's
1330 * Cannot setup the module hash here as my init() may not be called before
1331 * users start registering. So I will move the module_hash stuff to
1332 * proto_register_giop, as is done with packet-rpc
1336 * Also, setup our objectkey/repoid hash here.
1340 static void giop_init(void) {
1344 * Create objkey/repoid hash, use my "equal" and "hash" functions.
1348 if (giop_objkey_hash)
1349 g_hash_table_destroy(giop_objkey_hash);
1350 if (giop_objkey_keys)
1351 g_mem_chunk_destroy(giop_objkey_keys);
1352 if (giop_objkey_vals)
1353 g_mem_chunk_destroy(giop_objkey_vals);
1357 * Create hash, use my "equal" and "hash" functions.
1361 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1363 giop_objkey_keys = g_mem_chunk_new("giop_objkey_keys",
1364 sizeof(struct giop_object_key),
1365 giop_objkey_init_count * sizeof(struct giop_object_key),
1368 giop_objkey_vals = g_mem_chunk_new("giop_objkey_vals",
1369 sizeof(struct giop_object_val),
1370 giop_objkey_init_count * sizeof(struct giop_object_val),
1375 * Create complete_reply_hash, use my "equal" and "hash" functions.
1379 if (giop_complete_reply_hash)
1380 g_hash_table_destroy(giop_complete_reply_hash);
1381 if (giop_complete_reply_keys)
1382 g_mem_chunk_destroy(giop_complete_reply_keys);
1383 if (giop_complete_reply_vals)
1384 g_mem_chunk_destroy(giop_complete_reply_vals);
1388 * Create hash, use my "equal" and "hash" functions.
1392 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1394 giop_complete_reply_keys = g_mem_chunk_new("giop_complete_reply_keys",
1395 sizeof(struct complete_reply_hash_key),
1396 complete_reply_hash_count * sizeof(struct complete_reply_hash_key),
1399 giop_complete_reply_vals = g_mem_chunk_new("giop_complete_reply_vals",
1400 sizeof(struct complete_reply_hash_val),
1401 complete_reply_hash_count * sizeof(struct complete_reply_hash_val),
1406 read_IOR_strings_from_file("IOR.txt", 600); /* testing */
1413 * Insert an entry in the GIOP Heuristic User table.
1415 * Uses giop_sub_handle_t to wrap giop user info.
1419 void register_giop_user(giop_sub_dissector_t *sub, gchar *name, int sub_proto) {
1421 giop_sub_handle_t *subh;
1423 subh = g_malloc(sizeof (giop_sub_handle_t));
1425 subh->sub_name = name;
1427 subh->sub_proto = sub_proto; /* proto_XXX from sub dissectors's proto_register_protocol() */
1429 giop_sub_list = g_slist_append (giop_sub_list, subh);
1435 * Lookup an object key in our object key hash, and return the corresponding
1440 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1442 struct giop_object_key objkey_key;
1443 struct giop_object_val *objkey_val = NULL;
1445 objkey_key.objkey_len = len; /* length */
1446 objkey_key.objkey = obj; /* object key octet sequence */
1448 /* Look it up to see if it exists */
1450 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1454 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1456 return objkey_val->repo_id; /* found */
1460 printf("FAILED Lookup of object key \n" );
1463 return NULL; /* not found */
1469 * Extract top level module/interface from repoid
1471 * eg from - "IDL:Echo/interface1:1.0"
1474 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1475 * get linux.org/Penguin/Teeth
1478 * User must free returned ptr after use.
1480 * TODO -- generalize for other Repoid encodings
1483 static gchar * get_modname_from_repoid(gchar *repoid) {
1485 gchar *modname = NULL;
1486 gchar *saved_repoid = NULL;
1488 guint8 stop_mod; /* Index of last character of modname in Repoid */
1489 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1492 saved_repoid = g_strdup(repoid); /* make a copy */
1494 /* Must start with IDL: , otherwise I get confused */
1496 if (g_strncasecmp("IDL:",repoid,4))
1499 /* Looks like a RepoID to me, so get Module or interface name */
1501 /* TODO -- put some code here to get Module name */
1503 for(i=4; c != '\0'; i++) {
1505 stop_mod = i; /* save */
1506 if (c == ':' ) /* delimiters */
1511 /* Now create a new string based on start and stop and \0 */
1513 modname = g_strndup(repoid+4, stop_mod - start_mod);
1528 * Display a "module" hash entry
1531 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1533 struct giop_module_val *mv = (struct giop_module_val *) val;
1534 struct giop_module_key *mk = (struct giop_module_key *) key;
1536 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1543 * Display a "complete_reply " hash entry
1546 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1548 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1549 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1551 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1559 * Display an "objkey" hash entry
1562 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1564 struct giop_object_val *mv = (struct giop_object_val *) val;
1565 struct giop_object_key *mk = (struct giop_object_key *) key;
1568 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1570 for (i=0; i<mk->objkey_len; i++) {
1571 printf("%.2x ", mk->objkey[i]);
1575 * If read from file, mark it as such..
1579 printf(", Repo ID = %s \n", mv->repo_id);
1582 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1590 * Display all giop_sub_list (GSList) entries
1593 static void display_heuristic_user_list() {
1596 giop_sub_handle_t *subh; /* handle */
1598 /* Get length of list */
1599 len = g_slist_length(giop_sub_list); /* find length */
1604 for (i=0; i<len; i++) {
1605 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1606 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1612 * Display all complete_request_list (GList) entries
1615 static void display_complete_request_list() {
1618 comp_req_list_entry_t *entry;
1620 /* Get length of list */
1621 len = g_list_length(giop_complete_request_list); /* find length */
1626 for (i=0; i<len; i++) {
1627 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1628 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1629 entry->reqid,entry->operation, entry->repoid);
1637 /* Dump Hash/List contents
1639 * collection_type specifies the list or hash to dump
1643 static void giop_dump_collection(collection_data_t collection_type) {
1645 switch(collection_type) {
1646 case cd_heuristic_users:
1647 printf("+----------------------------------------------+ \n");
1648 printf("+-------------- Heuristic User (Begin) --------+ \n");
1649 printf("+----------------------------------------------+ \n");
1651 display_heuristic_user_list();
1653 printf("+----------------------------------------------+ \n");
1654 printf("+-------------- Heuristic User (End) ----------+ \n");
1655 printf("+----------------------------------------------+ \n");
1659 case cd_complete_request_list:
1660 printf("+----------------------------------------------+ \n");
1661 printf("+------------- Complete Request List (Begin) --+ \n");
1662 printf("+----------------------------------------------+ \n");
1664 display_complete_request_list();
1666 printf("+----------------------------------------------+ \n");
1667 printf("+------------ Complete Request List (End) -----+ \n");
1668 printf("+----------------------------------------------+ \n");
1672 case cd_module_hash:
1673 printf("+----------------------------------------------+ \n");
1674 printf("+-------------- Module (Begin) ----------------+ \n");
1675 printf("+----------------------------------------------+ \n");
1677 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1679 printf("+----------------------------------------------+ \n");
1680 printf("+-------------- Module ( End) -----------------+ \n");
1681 printf("+----------------------------------------------+ \n\n");
1685 case cd_objkey_hash:
1686 printf("+----------------------------------------------+ \n");
1687 printf("+-------------- Objkey (Begin) ----------------+ \n");
1688 printf("+----------------------------------------------+ \n");
1690 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1692 printf("+----------------------------------------------+ \n");
1693 printf("+-------------- Objkey (End) ------------------+ \n");
1694 printf("+----------------------------------------------+ \n\n");
1698 case cd_complete_reply_hash:
1699 printf("+----------------------------------------------+ \n");
1700 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1701 printf("+----------------------------------------------+ \n");
1703 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1705 printf("+----------------------------------------------+ \n");
1706 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1707 printf("+----------------------------------------------+ \n");
1713 printf("giop: giop_dump_collection: Unknown type \n");
1724 * Loop through all subdissectors, and call them until someone
1725 * answers (returns TRUE). This function then returns TRUE, otherwise
1728 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1731 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1732 MessageHeader *header, gchar *operation ) {
1735 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1736 giop_sub_handle_t *subh = NULL;
1738 len = g_slist_length(giop_sub_list); /* find length */
1743 for (i=0; i<len; i++) {
1744 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1746 if (proto_is_protocol_enabled(subh->sub_proto)) {
1747 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1749 return TRUE; /* found one, lets return */
1751 } /* protocol_is_enabled */
1754 return res; /* result */
1760 * Find the matching repoid in the module hash and call
1761 * the dissector function if offset exists.
1764 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1765 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1771 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1772 MessageHeader *header, gchar *operation, gchar *repoid ) {
1774 giop_sub_handle_t *subdiss = NULL; /* handle */
1775 gboolean res = FALSE;
1776 gchar *modname = NULL;
1777 struct giop_module_key module_key;
1778 struct giop_module_val *module_val = NULL;
1782 * Get top level module/interface from complete repoid
1785 modname = get_modname_from_repoid(repoid);
1788 /* Search for Module or interface name */
1790 module_key.module = modname; /* module name */
1791 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1793 if (module_val == NULL) {
1794 return res; /* module not registered */
1797 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1800 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1801 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1802 /* but only if user not clicking */
1804 if (!pinfo->fd->flags.visited)
1805 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1808 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1810 if (tvb_offset_exists(tvb, *offset)) {
1812 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1815 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1817 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1819 } /* protocol_is_enabled */
1820 } /* offset exists */
1823 return res; /* return result */
1828 /* Take in an array of char and create a new string.
1829 * Replace non-printable characters with periods.
1831 * The array may contain \0's so dont use strdup
1832 * The string is \0 terminated, and thus longer than
1833 * the initial sequence.
1834 * Caller must free the new string.
1837 static gchar * make_printable_string (gchar *in, guint32 len) {
1839 gchar *print_string = NULL;
1841 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1842 memcpy(print_string, in, len); /* and make a copy of input data */
1844 for(i=0; i < len; i++) {
1845 if( !isprint( (unsigned char)print_string[i] ) )
1846 print_string[i] = '.';
1849 return print_string; /* return ptr */
1852 /* Determine the byte order from the GIOP MessageHeader */
1854 gboolean is_big_endian (MessageHeader * header) {
1855 gboolean big_endian = FALSE;
1857 switch (header->GIOP_version.minor) {
1860 if (header->flags & 0x01)
1880 * Calculate new offset, based on the current offset, and user supplied
1881 * "offset delta" value, and the alignment requirement.
1885 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1886 * aligned on 8 byte boundaries.
1889 static void set_new_alignment(int *offset, int delta, int alignment) {
1891 while( ( (*offset + delta) % alignment) != 0)
1900 * ------------------------------------------------------------------------------------------+
1901 * Public get_CDR_xxx functions.
1902 * ------------------------------------------------------------------------------------------+
1908 * Gets data of type any. This is encoded as a TypeCode
1909 * followed by the encoded value.
1912 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1913 gboolean stream_is_big_endian, int boundary,
1914 MessageHeader * header ) {
1916 guint32 TCKind; /* TypeCode */
1918 /* get TypeCode of any */
1919 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1921 /* dissect data of type TCKind */
1922 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1926 /* Copy a 1 octet sequence from the tvbuff
1927 * which represents a boolean value, and convert
1928 * it to a boolean value.
1929 * Offset is then incremented by 1, to indicate the 1 octet which
1930 * has been processed.
1933 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1936 val = tvb_get_guint8(tvb, *offset); /* easy */
1941 /* Copy a 1 octet sequence from the tvbuff
1942 * which represents a char, and convert
1943 * it to an char value.
1944 * offset is then incremented by 1, to indicate the 1 octet which
1945 * has been processed.
1948 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1951 val = tvb_get_guint8(tvb, *offset); /* easy */
1959 * Floating Point Data Type double IEEE 754-1985
1961 * Copy an 8 octet sequence from the tvbuff
1962 * which represents a double value, and convert
1963 * it to a double value, taking into account byte order.
1964 * offset is first incremented so that it falls on a proper alignment
1965 * boundary for double values.
1966 * offset is then incremented by 8, to indicate the 8 octets which
1967 * have been processed.
1970 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1973 guint8 e1,e2,f1,f2,f3,f4,f5,f6,f7;
1976 guint32 fract0, fract1;
1980 /* double values must be aligned on a 8 byte boundary */
1982 while( ( (*offset + boundary) % 8) != 0)
1986 if(stream_is_big_endian) {
1987 e1 = get_CDR_octet(tvb,offset);
1988 sign = e1 >> 7; /* sign value */
1989 e1 &= 0x7f; /* bottom 7 bits */
1990 f1 = get_CDR_octet(tvb,offset);
1992 f1 &= 0x0f; /* bottom 4 bits */
1993 f2 = get_CDR_octet(tvb,offset);
1994 f3 = get_CDR_octet(tvb,offset);
1995 f4 = get_CDR_octet(tvb,offset);
1996 f5 = get_CDR_octet(tvb,offset);
1997 f6 = get_CDR_octet(tvb,offset);
1998 f7 = get_CDR_octet(tvb,offset);
2002 f7 = get_CDR_octet(tvb,offset);
2003 f6 = get_CDR_octet(tvb,offset);
2004 f5 = get_CDR_octet(tvb,offset);
2005 f4 = get_CDR_octet(tvb,offset);
2006 f3 = get_CDR_octet(tvb,offset);
2007 f2 = get_CDR_octet(tvb,offset);
2008 f1 = get_CDR_octet(tvb,offset);
2010 f1 &= 0x0f; /* bottom 4 bits */
2011 e1 = get_CDR_octet(tvb,offset);
2012 sign = e1 >> 7; /* sign value */
2013 e1 &= 0x7f; /* bottom 7 bits */
2017 exp = (e1 << 4) + e2;
2019 /* Now lets do some 52 bit math with 32 bit constraint */
2021 fract0 = f7 + (f6 << 8) + (f5 << 16) + (f4 << 24); /* lower 32 bits of fractional part */
2022 fract1 = f3 + (f2 << 8) + (f1 << 16); /* top 20 bits of fractional part */
2024 d_fract = (fract1 / (pow(2,20))) + (fract0 / (pow(2,52))); /* 52 bits represent a fraction */
2026 val = pow(-1,sign) * pow(2,(exp - 1023)) * (1 + d_fract);
2028 return val; /* FIX rounding ?? */
2033 /* Copy a 4 octet sequence from the tvbuff
2034 * which represents an enum value, and convert
2035 * it to an enum value, taking into account byte order.
2036 * offset is first incremented so that it falls on a proper alignment
2037 * boundary for an enum (4)
2038 * offset is then incremented by 4, to indicate the 4 octets which
2039 * have been processed.
2041 * Enum values are encoded as unsigned long.
2045 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2047 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2053 * Copy an octet sequence from the tvbuff
2054 * which represents a Fixed point decimal type, and create a string representing
2055 * a Fixed point decimal type. There are no alignment restrictions.
2056 * Size and scale of fixed decimal type is determined by IDL.
2058 * digits - IDL specified number of "digits" for this fixed type
2059 * scale - IDL specified "scale" for this fixed type
2062 * eg: typedef fixed <5,2> fixed_t;
2063 * could represent numbers like 123.45, 789.12,
2066 * As the fixed type could be any size, I will not try to fit it into our
2067 * simple types like gdouble or glong etc. I will just create a string buffer holding
2068 * a representation (after scale is applied), and with a decimal point or zero padding
2069 * inserted at the right place if necessary. The string is null terminated
2071 * so string may look like
2074 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2076 * According to spec, digits <= 31
2077 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2080 * User must remember to free the buffer
2085 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2087 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2088 guint32 i ; /* loop */
2089 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2090 /* this does not include sign, decimal point and \0 */
2091 guint32 sindex = 0; /* string index */
2092 gchar *tmpbuf = NULL; /* temp buff, holds string without scaling */
2093 guint8 tval; /* temp val storage */
2096 * how many bytes to hold digits and scale (if scale <0)
2098 * eg: fixed <5,2> = 5 digits
2099 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2103 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2107 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2109 slen = digits; /* digits */
2113 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2116 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2118 /* If even , grab 1st dig */
2120 if (!(digits & 0x01)) {
2121 tval = get_CDR_octet(tvb,offset);
2123 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2125 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2130 * Loop, but stop BEFORE we hit last digit and sign
2131 * if digits = 1 or 2, then this part is skipped
2135 for(i=0; i< ((digits-1)/2 ); i++) {
2136 tval = get_CDR_octet(tvb,offset);
2138 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2141 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2143 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2150 printf("giop:get_CDR_fixed(): before last digit \n");
2154 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2156 tval = get_CDR_octet(tvb,offset);
2158 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2160 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2163 sign = tval & 0x0f; /* get sign */
2165 /* So now, we have all digits in an array, and the sign byte
2166 * so lets generate a printable string, taking into account the scale
2170 sindex = 0; /* reset */
2171 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2172 * \0 -- TODO check slen is reasonable first */
2174 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2179 (*seq)[sindex] = '+'; /* put sign in first string position */
2182 (*seq)[sindex] = '-';
2185 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2186 (*seq)[sindex] = '*'; /* flag as sign unkown */
2192 /* Add decimal point or padding 0's, depending if scale is positive or
2193 * negative, respectively
2197 for (i=0; i<digits-scale; i++) {
2198 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2202 (*seq)[sindex] = '.'; /* decimal point */
2205 for (i=digits-scale; i<digits; i++) {
2206 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2210 (*seq)[sindex] = '\0'; /* string terminator */
2214 /* negative scale, dump digits and pad out with 0's */
2216 for (i=0; i<digits-scale; i++) {
2218 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2220 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2225 (*seq)[sindex] = '\0'; /* string terminator */
2229 g_free(tmpbuf); /* release temp buffer */
2233 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2243 * Floating Point Data Type float IEEE 754-1985
2245 * Copy an 4 octet sequence from the tvbuff
2246 * which represents a float value, and convert
2247 * it to a float value, taking into account byte order.
2248 * offset is first incremented so that it falls on a proper alignment
2249 * boundary for float values.
2250 * offset is then incremented by 4, to indicate the 4 octets which
2251 * have been processed.
2254 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2257 guint8 e1,e2,f1,f2,f3;
2263 /* float values must be aligned on a 4 byte boundary */
2265 while( ( (*offset + boundary) % 4) != 0)
2268 if(stream_is_big_endian) {
2269 e1 = get_CDR_octet(tvb,offset);
2270 sign = e1 >> 7; /* sign value */
2271 e1 &= 0x7f; /* bottom 7 bits */
2272 f1 = get_CDR_octet(tvb,offset);
2274 f1 &= 0x7f; /* bottom 7 bits */
2275 f2 = get_CDR_octet(tvb,offset);
2276 f3 = get_CDR_octet(tvb,offset);
2280 f3 = get_CDR_octet(tvb,offset);
2281 f2 = get_CDR_octet(tvb,offset);
2282 f1 = get_CDR_octet(tvb,offset);
2284 f1 &= 0x7f; /* bottom 7 bits */
2285 e1 = get_CDR_octet(tvb,offset);
2286 sign = e1 >> 7; /* sign value */
2287 e1 &= 0x7f; /* bottom 7 bits */
2292 exp = (e1 << 1) + e2;
2293 fract = f3 + (f2 << 8) + (f1 << 16);
2295 d_fract = fract / (pow(2,23)); /* 23 bits represent a fraction */
2297 val = pow(-1,sign) * pow(2,(exp - 127)) * (1 + d_fract);
2299 return val; /* FIX rounding ?? */
2305 * Decode an Interface type, and display it on the tree.
2308 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2309 gboolean stream_is_big_endian, int boundary) {
2312 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2318 /* Copy a 4 octet sequence from the tvbuff
2319 * which represents a signed long value, and convert
2320 * it to an signed long vaule, taking into account byte order.
2321 * offset is first incremented so that it falls on a proper alignment
2322 * boundary for long values.
2323 * offset is then incremented by 4, to indicate the 4 octets which
2324 * have been processed.
2327 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2331 /* unsigned long values must be aligned on a 4 byte boundary */
2332 while( ( (*offset + boundary) % 4) != 0)
2335 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2336 tvb_get_letohl (tvb, *offset);
2343 * Decode an Object type, and display it on the tree.
2346 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2347 gboolean stream_is_big_endian, int boundary) {
2349 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2355 /* Copy a 1 octet sequence from the tvbuff
2356 * which represents a octet, and convert
2357 * it to an octet value.
2358 * offset is then incremented by 1, to indicate the 1 octet which
2359 * has been processed.
2362 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2365 val = tvb_get_guint8(tvb, *offset); /* easy */
2371 /* Copy a sequence of octets from the tvbuff.
2372 * Caller of this function must remember to free the
2373 * array pointed to by seq.
2374 * This function also increments offset by len.
2377 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, int len) {
2379 if (! tvb_bytes_exist(tvb, *offset,len)) {
2380 tvb_get_guint8(tvb,100000); /* generate an exception, and stop processing */
2381 /* better than a core dump later */
2384 *seq = g_new0(gchar, len + 1);
2385 tvb_memcpy( tvb, *seq, *offset, len);
2390 /* Copy a 2 octet sequence from the tvbuff
2391 * which represents a signed short value, and convert
2392 * it to a signed short value, taking into account byte order.
2393 * offset is first incremented so that it falls on a proper alignment
2394 * boundary for short values.
2395 * offset is then incremented by 2, to indicate the 2 octets which
2396 * have been processed.
2399 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2403 /* short values must be aligned on a 2 byte boundary */
2404 while( ( (*offset + boundary) % 2) != 0)
2407 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2408 tvb_get_letohs (tvb, *offset);
2416 /* Copy an octet sequence from the tvbuff
2417 * which represents a string, and convert
2418 * it to an string value, taking into account byte order.
2419 * offset is first incremented so that it falls on a proper alignment
2420 * boundary for string values. (begins with an unsigned long LI)
2422 * String sequence is copied to a buffer "seq". This must
2423 * be freed by the calling program.
2424 * offset is then incremented, to indicate the octets which
2425 * have been processed.
2427 * returns number of octets in the sequence
2429 * Note: This function only supports single byte encoding at the
2430 * moment until I get a handle on multibyte encoding etc.
2435 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2440 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2442 /* Avoid crashing */
2444 if (! tvb_bytes_exist(tvb, *offset, slength)) {
2445 tvb_get_guint8(tvb,100000); /* generate an exception, and stop processing */
2446 /* better than a core dump later */
2450 (*offset)++; /* must step past \0 delimiter */
2454 get_CDR_octet_seq(tvb, seq, offset, slength);
2457 return slength; /* return length */
2461 /* Process a sequence of octets that represent the
2462 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2464 * This function also increments offset to the correct position.
2466 * It will parse the TypeCode and output data to the "tree" provided
2469 * It returns a guint32 representing a TCKind value.
2472 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2473 gboolean stream_is_big_endian, int boundary,
2474 MessageHeader * header ) {
2477 gint16 s_octet2; /* signed int16 */
2478 guint16 u_octet2; /* unsigned int16 */
2479 guint32 u_octet4; /* unsigned int32 */
2481 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2483 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2484 *offset-sizeof(val),4,val);
2487 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2490 case tk_null: /* empty parameter list */
2492 case tk_void: /* empty parameter list */
2494 case tk_short: /* empty parameter list */
2496 case tk_long: /* empty parameter list */
2498 case tk_ushort: /* empty parameter list */
2500 case tk_ulong: /* empty parameter list */
2502 case tk_float: /* empty parameter list */
2504 case tk_double: /* empty parameter list */
2506 case tk_boolean: /* empty parameter list */
2508 case tk_char: /* empty parameter list */
2510 case tk_octet: /* empty parameter list */
2512 case tk_any: /* empty parameter list */
2514 case tk_TypeCode: /* empty parameter list */
2516 case tk_Principal: /* empty parameter list */
2518 case tk_objref: /* complex parameter list */
2519 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2521 case tk_struct: /* complex parameter list */
2522 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2524 case tk_union: /* complex parameter list */
2525 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2527 case tk_enum: /* complex parameter list */
2528 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2531 case tk_string: /* simple parameter list */
2532 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2534 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2535 *offset-sizeof(u_octet4),4,u_octet4);
2539 case tk_sequence: /* complex parameter list */
2540 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2542 case tk_array: /* complex parameter list */
2543 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2545 case tk_alias: /* complex parameter list */
2546 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2548 case tk_except: /* complex parameter list */
2549 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2551 case tk_longlong: /* empty parameter list */
2553 case tk_ulonglong: /* empty parameter list */
2555 case tk_longdouble: /* empty parameter list */
2557 case tk_wchar: /* empty parameter list */
2559 case tk_wstring: /* simple parameter list */
2560 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2562 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2563 *offset-sizeof(u_octet4),4,u_octet4);
2567 case tk_fixed: /* simple parameter list */
2568 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2570 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2571 *offset-sizeof(u_octet2),2,u_octet2);
2574 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2576 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2577 *offset-sizeof(s_octet2),2,s_octet2);
2581 case tk_value: /* complex parameter list */
2582 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2584 case tk_value_box: /* complex parameter list */
2585 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2587 case tk_native: /* complex parameter list */
2588 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2590 case tk_abstract_interface: /* complex parameter list */
2591 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2594 g_warning("giop: Unknown TCKind %u \n", val);
2603 /* Copy a 4 octet sequence from the tvbuff
2604 * which represents an unsigned long value, and convert
2605 * it to an unsigned long vaule, taking into account byte order.
2606 * offset is first incremented so that it falls on a proper alignment
2607 * boundary for unsigned long values.
2608 * offset is then incremented by 4, to indicate the 4 octets which
2609 * have been processed.
2612 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2616 /* unsigned long values must be aligned on a 4 byte boundary */
2617 while( ( (*offset + boundary) % 4) != 0)
2620 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2621 tvb_get_letohl (tvb, *offset);
2628 /* Copy a 2 octet sequence from the tvbuff
2629 * which represents an unsigned short value, and convert
2630 * it to an unsigned short value, taking into account byte order.
2631 * offset is first incremented so that it falls on a proper alignment
2632 * boundary for unsigned short values.
2633 * offset is then incremented by 2, to indicate the 2 octets which
2634 * have been processed.
2637 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2641 /* unsigned short values must be aligned on a 2 byte boundary */
2642 while( ( (*offset + boundary) % 2) != 0)
2645 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2646 tvb_get_letohs (tvb, *offset);
2654 /* Copy a wchar from the tvbuff.
2655 * Caller of this function must remember to free the
2656 * array pointed to by seq.
2657 * This function also increments offset according to
2660 * For GIOP 1.1 read 2 octets and return size -2. The
2661 * negation means there is no size element in the packet
2662 * and therefore no size to add to the tree.
2664 * For GIOP 1.2 read size of wchar and the size
2665 * octets. size is returned as a gint8.
2667 * For both GIOP versions the wchar is returned
2668 * as a printable string.
2672 /* NOTE: This is very primitive in that it just reads
2673 * the wchar as a series of octets and returns them
2674 * to the user. No translation is attempted based on
2675 * byte orientation, nor on code set. I.e it only
2676 * really reads past the wchar and sets the offset
2680 /* The "decoding" is done according to CORBA chapter 15.
2681 * Wchar is not supported for GIOP 1.0.
2684 gint8 get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2687 gchar *raw_wstring = NULL;
2689 /* CORBA chapter 15:
2690 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2691 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2692 * followed by the elements of the octet sequence representing
2693 * the encoded value of the wchar.
2696 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2697 slength = 2; /* set for GIOP 1.1 length in octets */
2699 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2700 slength = get_CDR_octet(tvb,offset);
2703 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2704 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2706 /* now turn octets (wchar) into something that can be printed by the user */
2707 *seq = make_printable_string(raw_wstring, slength);
2710 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2711 if (header->GIOP_version.minor < 2)
2714 g_free(raw_wstring);
2716 return slength; /* return length */
2721 /* Copy a wstring from the tvbuff.
2722 * Caller of this function must remember to free the
2723 * array pointed to by seq.
2724 * This function also increments offset, according to
2725 * wstring length. length is returned as guint32
2728 /* NOTE: This is very primitive in that it just reads
2729 * the wstring as a series of octets and returns them
2730 * to the user. No translation is attempted based on
2731 * byte orientation, nor on code set. I.e it only
2732 * really reads past the wstring and sets the offset
2736 /* The "decoding" is done according to CORBA chapter 15.
2737 * Wstring is not supported for GIOP 1.0.
2741 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2742 int boundary, MessageHeader * header) {
2745 gchar *raw_wstring = NULL;
2747 /* CORBA chapter 15:
2748 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2749 * length and string are NUL terminated (length???).
2750 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2754 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2756 /* get length, same for all GIOP versions,
2757 * although for 1.2 CORBA doesnt say, so assume.
2759 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2763 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2764 slength = 5; /* better than core dumping during debug */
2768 if (header->GIOP_version.minor < 2) {
2770 (*offset)++; /* must step past \0 delimiter */
2772 /* assume length is number of characters and not octets, spec not clear */
2773 slength = slength * 2; /* length in octets is 2 * wstring length */
2777 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2779 /* now turn octets (wstring) into something that can be printed by the user */
2780 *seq = make_printable_string(raw_wstring, slength);
2783 g_free(raw_wstring);
2785 return slength; /* return length */
2792 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2794 * typedef short AddressingDisposition;
2795 * const short KeyAddr = 0;
2796 * const short ProfileAddr = 1;
2797 * const short ReferenceAddr = 2;
2798 * struct IORAddressingInfo {
2799 * unsigned long selected_profile_index;
2803 * union TargetAddress switch (AddressingDisposition) {
2804 * case KeyAddr: sequence <octet> object_key;
2805 * case ProfileAddr: IOP::TaggedProfile profile;
2806 * case ReferenceAddr: IORAddressingInfo ior;
2811 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2812 MessageHeader * header, gboolean stream_is_big_endian)
2814 guint16 discriminant;
2815 gchar *object_key = NULL;
2816 gchar *p_object_key = NULL;
2820 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2823 proto_tree_add_text (tree, tvb, *offset -2, 2,
2824 "TargetAddress Discriminant: %u", discriminant);
2827 switch (discriminant)
2829 case 0: /* KeyAddr */
2830 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2833 proto_tree_add_text (tree, tvb, *offset -4, 4,
2834 "KeyAddr (object key length): %u", len);
2839 get_CDR_octet_seq(tvb, &object_key, offset, len);
2840 p_object_key = make_printable_string( object_key, len );
2844 proto_tree_add_text (tree, tvb, *offset -len, len,
2845 "KeyAddr (object key): %s", p_object_key);
2849 case 1: /* ProfileAddr */
2850 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2851 stream_is_big_endian, NULL);
2853 case 2: /* ReferenceAddr */
2854 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2858 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2859 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2862 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2867 g_free( object_key );
2868 g_free( p_object_key );
2872 dissect_reply_body (tvbuff_t *tvb, u_int offset, packet_info *pinfo,
2873 proto_tree *tree, gboolean stream_is_big_endian,
2874 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2876 u_int sequence_length;
2877 gboolean exres = FALSE; /* result of trying explicit dissectors */
2878 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2881 * comp_req_list stuff
2884 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2888 switch (reply_status)
2890 case SYSTEM_EXCEPTION:
2892 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2895 case USER_EXCEPTION:
2899 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2901 proto_tree_add_text(tree, tvb, offset-4, 4,
2902 "Exception length: %u", sequence_length);
2904 if (sequence_length != 0)
2906 proto_tree_add_text(tree, tvb, offset, sequence_length,
2908 tvb_format_text(tvb, offset, sequence_length));
2912 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2914 /* read exception id from buffer and store in*/
2916 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2922 offset += sequence_length;
2930 * Now just fall through to the NO_EXCEPTION part
2931 * as this is common .
2939 /* lookup MFN in hash directly */
2941 mfn = get_mfn_from_fn(pinfo->fd->num);
2943 if (mfn == pinfo->fd->num)
2944 return; /* no matching frame number, what am I */
2946 /* get entry for this MFN */
2947 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2950 return; /* no matching entry */
2954 * If this packet is a REPLY to a RESOLVE(request)
2956 * TODO - make this lookup faster -- FS
2959 if (!strcmp(giop_op_resolve,entry->operation)) {
2960 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2964 /* TODO -- Put stuff here for other "interesting operations" */
2968 * Call sub dissector.
2969 * First try an find a explicit sub_dissector, then if that
2970 * fails, try the heuristic method.
2975 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
2978 /* Only call heuristic if no explicit dixxector was found */
2981 try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
2987 case LOCATION_FORWARD:
2988 g_warning("giop: We don't yet dissect LOCATION_FORWARD\n");
2992 case LOCATION_FORWARD_PERM:
2993 g_warning("giop: We don't yet dissect LOCATION_FORWARD_PERM\n");
2997 case NEEDS_ADDRESSING_MODE:
2998 g_warning("giop: We don't yet dissect NEEDS_ADDRESSING_MODE\n");
3004 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
3010 g_free(repoid); /* free resource */
3020 /* The format of the Reply Header for GIOP 1.0 and 1.1
3021 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
3023 struct ReplyHeader_1_0 {
3024 IOP::ServiceContextList service_context;
3025 unsigned long request_id;
3026 ReplyStatusType_1_0 reply_status;
3030 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3031 proto_tree * clnp_tree, MessageHeader * header,
3032 gboolean stream_is_big_endian) {
3036 guint32 reply_status;
3037 proto_tree *reply_tree = NULL;
3039 guint32 mfn; /* matching frame number */
3042 tf = proto_tree_add_text (tree, tvb, offset,
3044 "General Inter-ORB Protocol Reply");
3045 if (reply_tree == NULL)
3047 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3053 * Decode IOP::ServiceContextList
3056 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3058 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3060 if (check_col(pinfo->fd, COL_INFO)) {
3061 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3065 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3066 "Request id: %u", request_id);
3069 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3071 if (check_col(pinfo->fd, COL_INFO)) {
3072 col_append_fstr(pinfo->fd, COL_INFO, ": %s",
3073 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3078 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3080 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3085 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3088 if (! pinfo->fd->flags.visited) {
3089 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3090 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3091 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3095 header->req_id = request_id; /* save for sub dissector */
3096 header->rep_status = reply_status; /* save for sub dissector */
3098 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3099 reply_status, header,tree);
3104 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3105 * and 1.1 header, only the fields have been rearranged. From Section
3106 * 15.4.3.1 of the CORBA 2.4 specification:
3108 * struct ReplyHeader_1_2 {
3109 * unsigned long request_id;
3110 * ReplyStatusType_1_2 reply_status;
3111 * IOP:ServiceContextList service_context;
3115 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3116 proto_tree * tree, proto_tree * clnp_tree,
3117 MessageHeader * header,
3118 gboolean stream_is_big_endian) {
3122 guint32 reply_status;
3123 proto_tree *reply_tree = NULL;
3125 guint32 mfn; /* matching frame number */
3128 tf = proto_tree_add_text (tree, tvb, offset,
3130 "General Inter-ORB Protocol Reply");
3131 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3134 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3136 if (check_col(pinfo->fd, COL_INFO)) {
3137 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3141 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3142 "Request id: %u", request_id);
3145 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3147 if (check_col(pinfo->fd, COL_INFO)) {
3148 col_append_fstr(pinfo->fd, COL_INFO, ": %s",
3149 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3154 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3156 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3161 * Decode IOP::ServiceContextList
3164 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3167 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3170 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3173 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3176 if (! pinfo->fd->flags.visited) {
3177 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3178 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3179 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3184 * Add header to argument list so sub dissector can get header info.
3187 header->req_id = request_id; /* save for sub dissector */
3188 header->rep_status = reply_status; /* save for sub dissector */
3190 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3191 reply_status,header,tree);
3197 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3198 proto_tree * tree, proto_tree * clnp_tree,
3199 MessageHeader * header, gboolean stream_is_big_endian) {
3203 proto_tree *cancel_request_tree = NULL;
3207 tf = proto_tree_add_text (tree, tvb, offset,
3209 "General Inter-ORB Protocol CancelRequest");
3210 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3213 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3215 if (check_col(pinfo->fd, COL_INFO)) {
3216 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3220 proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4,
3221 "Request id: %u", request_id);
3227 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3228 * in section 15.4.2.1 of the CORBA 2.4 specification.
3230 * struct RequestHeader{
3231 * IOP::ServiceContextList service_context;
3232 * unsigned long request_id;
3233 * boolean response_expected;
3234 * octet reserved[3]; // Only in GIOP 1.1
3235 * sequence<octet> object_key;
3237 * CORBA::OctetSeq requesting_principal;
3241 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3242 proto_tree * tree, proto_tree * clnp_tree,
3243 MessageHeader * header, gboolean stream_is_big_endian)
3249 guint32 objkey_len = 0; /* object key length */
3250 gchar *objkey = NULL; /* object key sequence */
3251 gchar *print_objkey = NULL; /* printable object key sequence */
3252 gboolean exres = FALSE; /* result of trying explicit dissectors */
3254 gchar *operation = NULL;
3255 gchar *requesting_principal = NULL;
3256 gchar *print_requesting_principal = NULL;
3257 guint8 response_expected;
3258 gchar *reserved = NULL;
3259 proto_tree *request_tree = NULL;
3262 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3267 tf = proto_tree_add_text (tree, tvb, offset,
3269 "General Inter-ORB Protocol Request");
3270 if (request_tree == NULL)
3272 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3281 * Decode IOP::ServiceContextList
3284 decode_ServiceContextList(tvb, pinfo, request_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3287 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3288 if (check_col(pinfo->fd, COL_INFO))
3290 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3294 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3295 "Request id: %u", request_id);
3298 response_expected = tvb_get_guint8( tvb, offset );
3300 if (check_col(pinfo->fd, COL_INFO))
3302 col_append_fstr(pinfo->fd, COL_INFO, " (%s)",
3303 response_expected ? "two-way" : "one-way");
3307 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3308 "Response expected: %u", response_expected);
3311 if( header->GIOP_version.minor > 0)
3313 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3316 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3317 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3323 /* Length of object_key sequence */
3324 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3329 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3330 /**/ "Object Key length: %u", objkey_len);
3335 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3337 print_objkey = make_printable_string(objkey, objkey_len);
3341 proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
3342 /**/ "Object Key: %s", print_objkey);
3347 /* length of operation string and string */
3348 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3351 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3352 /**/ "Operation length: %u", len);
3357 if (check_col(pinfo->fd, COL_INFO))
3359 col_append_fstr(pinfo->fd, COL_INFO, ": %s", operation);
3363 proto_tree_add_text (request_tree, tvb, offset - len, len,
3364 /**/ "Operation: %s", operation);
3369 /* length of requesting_principal string */
3370 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3373 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3374 /**/ "Requesting Principal Length: %u", len);
3379 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3381 print_requesting_principal = make_printable_string(requesting_principal, len);
3385 proto_tree_add_text (request_tree, tvb, offset - len, len,
3386 /**/ "Requesting Principal: %s", print_requesting_principal);
3393 * Save FN,reqid,and operation for later. Add sub_handle later.
3394 * But only if user is NOT clicking.
3397 if (! pinfo->fd->flags.visited)
3398 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3399 request_id,operation,NULL);
3403 * Call subdissector here before freeing "operation" and "key"
3404 * pass request_id also.
3405 * First try an find an explicit sub_dissector, then if that
3406 * fails, try the heuristic method.
3411 header->req_id = request_id; /* save for sub dissector */
3412 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3416 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3419 /* Only call heuristic if no explicit dissector was found */
3422 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3426 g_free( print_objkey );
3428 g_free( operation );
3429 g_free( requesting_principal );
3430 g_free( print_requesting_principal );
3434 /** The format of a GIOP 1.2 RequestHeader message is
3435 * (CORBA 2.4, sec. 15.4.2):
3437 * struct RequestHeader_1_2 {
3438 * unsigned long request_id;
3439 * octet response_flags;
3440 * octet reserved[3];
3441 * TargetAddress target;
3443 * IOP::ServiceContextList service_context;
3444 * // requesting_principal not in GIOP 1.2
3448 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3449 proto_tree * tree, proto_tree * clnp_tree,
3450 MessageHeader * header, gboolean stream_is_big_endian)
3455 guint8 response_flags;
3456 gchar *reserved = NULL;
3457 gchar *operation = NULL;
3458 proto_tree *request_tree = NULL;
3460 gboolean exres = FALSE; /* result of trying explicit dissectors */
3462 gchar *repoid = NULL;
3467 tf = proto_tree_add_text (tree, tvb, offset,
3469 "General Inter-ORB Protocol Request");
3470 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3473 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3474 if (check_col(pinfo->fd, COL_INFO))
3476 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3480 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3481 "Request id: %u", request_id);
3484 response_flags = tvb_get_guint8( tvb, offset );
3488 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3489 "Response flags: %s (%u)",
3490 match_strval(response_flags, sync_scope),
3494 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3497 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3498 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3501 dissect_target_address(tvb, pinfo, &offset, request_tree, header, stream_is_big_endian);
3503 /* length of operation string */
3504 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3507 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3508 /**/ "Operation length: %u", len);
3513 if (check_col(pinfo->fd, COL_INFO))
3515 col_append_fstr(pinfo->fd, COL_INFO, ": %s", operation);
3519 proto_tree_add_text (request_tree, tvb, offset - len, len,
3520 /**/ "Operation: %s", operation);
3527 * Decode IOP::ServiceContextList
3530 decode_ServiceContextList(tvb, pinfo, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3533 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3534 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3535 * GIOP octet stream start.
3538 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3541 * Save FN,reqid,and operation for later. Add sub_handle later.
3542 * But only if user is NOT clicking.
3545 if (! pinfo->fd->flags.visited)
3546 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3547 request_id,operation,NULL);
3551 * Call sub dissector.
3552 * First try an find a explicit sub_dissector, then if that
3553 * fails, try the heuristic method.
3558 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3561 /* Only call heuristic if no explicit dissector was found */
3564 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3574 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3575 proto_tree * tree, MessageHeader * header,
3576 gboolean stream_is_big_endian)
3581 gchar *object_key = NULL;
3582 gchar *p_object_key = NULL;
3583 proto_tree *locate_request_tree = NULL;
3588 tf = proto_tree_add_text (tree, tvb, offset,
3590 "General Inter-ORB Locate Request");
3591 if (locate_request_tree == NULL)
3593 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3598 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3599 if (check_col(pinfo->fd, COL_INFO))
3601 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3603 if (locate_request_tree)
3605 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3606 "Request id: %u", request_id);
3609 if(header->GIOP_version.minor < 2)
3611 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3612 if (locate_request_tree)
3614 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3615 "Object Key length: %u", len);
3619 get_CDR_octet_seq(tvb, &object_key, &offset, len);
3621 p_object_key = make_printable_string(object_key, len);
3623 if(locate_request_tree)
3626 proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
3627 "Object Key: %s", p_object_key);
3631 else /* GIOP 1.2 and higher */
3633 dissect_target_address(tvb, pinfo, &offset, locate_request_tree, header,
3634 stream_is_big_endian);
3638 g_free(p_object_key);
3642 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3643 proto_tree * tree, MessageHeader * header,
3644 gboolean stream_is_big_endian)
3648 guint32 locate_status;
3651 proto_tree *locate_reply_tree = NULL;
3656 tf = proto_tree_add_text (tree, tvb, offset,
3658 "General Inter-ORB Locate Reply");
3659 if (locate_reply_tree == NULL)
3661 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3666 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3667 if (check_col(pinfo->fd, COL_INFO))
3669 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3671 if (locate_reply_tree)
3673 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3674 "Request id: %u", request_id);
3677 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3678 if (locate_reply_tree)
3680 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3681 "Locate status: %s",
3682 match_strval(locate_status, giop_locate_status_types)
3686 /* Decode the LocateReply body.
3688 * For GIOP 1.0 and 1.1 body immediately follows header.
3689 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3693 if (header->GIOP_version.minor > 1) {
3694 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3698 switch(locate_status) {
3699 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3700 case OBJECT_FORWARD_PERM:
3701 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3703 case LOC_SYSTEM_EXCEPTION:
3704 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3706 case LOC_NEEDS_ADDRESSING_MODE:
3707 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3708 if(locate_reply_tree) {
3709 proto_tree_add_text (tree, tvb, offset -2, 2,
3710 "AddressingDisposition: %u", addr_disp);
3713 default: /* others have no reply body */
3720 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3721 MessageHeader * header, gboolean stream_is_big_endian)
3725 proto_tree *fragment_tree = NULL;
3730 tf = proto_tree_add_text (tree, tvb, offset,
3732 "General Inter-ORB Fragment");
3733 if (fragment_tree == NULL)
3735 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3740 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3741 if (check_col(pinfo->fd, COL_INFO))
3743 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3747 proto_tree_add_text (fragment_tree, tvb, offset-4, 4,
3748 "Request id: %u", request_id);
3754 /* Main entry point */
3756 gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3758 MessageHeader header;
3759 tvbuff_t *giop_header_tvb;
3760 tvbuff_t *payload_tvb;
3762 proto_tree *clnp_tree = NULL;
3765 u_int minor_version;
3766 gboolean stream_is_big_endian;
3772 giop_dump_collection(cd_module_hash);
3773 giop_dump_collection(cd_objkey_hash);
3774 giop_dump_collection(cd_heuristic_users);
3775 giop_dump_collection(cd_complete_reply_hash);
3776 giop_dump_collection(cd_complete_request_list);
3780 /* check magic number and version */
3783 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
3785 if (tvb_length_remaining(tvb, 0) < GIOP_HEADER_SIZE)
3787 /* Not enough data captured to hold the GIOP header; don't try
3788 to interpret it as GIOP. */
3792 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3793 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3796 * because I have added extra elements in MessageHeader struct
3797 * for sub dissectors. -- FS
3800 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3802 if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
3804 /* Not a GIOP message. */
3809 if (check_col (pinfo->fd, COL_PROTOCOL))
3811 col_set_str (pinfo->fd, COL_PROTOCOL, "GIOP");
3814 if (header.GIOP_version.major != GIOP_MAJOR ||
3815 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3817 /* Bad version number; should we note that and dissect the rest
3818 as data, or should we return FALSE on the theory that it
3819 might have been some other packet that happened to begin with
3820 "GIOP"? We shouldn't do *both*, so we return TRUE, for now.
3821 If we should return FALSE, we should do so *without* setting
3822 the "Info" column, *without* setting the "Protocol" column,
3823 and *without* adding anything to the protocol tree. */
3825 if (check_col (pinfo->fd, COL_INFO))
3827 col_add_fstr (pinfo->fd, COL_INFO, "Version %u.%u",
3828 header.GIOP_version.major, header.GIOP_version.minor);
3832 ti = proto_tree_add_item (tree, proto_giop, tvb, 0,
3833 tvb_length (tvb), FALSE);
3834 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3835 proto_tree_add_text (clnp_tree, giop_header_tvb, 0,
3836 tvb_length (giop_header_tvb),
3837 "Version %u.%u not supported",
3838 header.GIOP_version.major,
3839 header.GIOP_version.minor);
3841 dissect_data (payload_tvb, 0, pinfo, tree);
3845 if (check_col (pinfo->fd, COL_INFO))
3847 col_add_fstr (pinfo->fd, 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->fd, COL_INFO))
3904 col_add_fstr (pinfo->fd, 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, clnp_tree,
3917 &header, stream_is_big_endian);
3921 dissect_giop_request_1_2 (payload_tvb, pinfo, tree, clnp_tree,
3922 &header, stream_is_big_endian);
3929 if(header.GIOP_version.minor < 2)
3931 dissect_giop_reply (payload_tvb, pinfo, tree, clnp_tree, &header,
3932 stream_is_big_endian);
3936 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree, clnp_tree,
3937 &header, stream_is_big_endian);
3941 dissect_giop_cancel_request(payload_tvb, pinfo, tree, clnp_tree,
3942 &header, 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, &header,
3954 stream_is_big_endian);
3959 } /* switch message_type */
3968 proto_register_giop (void)
3970 static hf_register_info hf[] = {
3971 { &hf_giop_message_type,
3972 { "Message type", "giop.type",
3973 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
3976 { &hf_giop_message_size,
3977 { "Message size", "giop.len",
3978 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3982 { "Repository ID", "giop.repoid",
3983 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
3986 { &hf_giop_string_length,
3987 { "String Length", "giop.strlen",
3988 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3991 { &hf_giop_sequence_length,
3992 { "Sequence Length", "giop.seqlen",
3993 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3996 { &hf_giop_profile_id,
3997 { "Profile ID", "giop.profid",
3998 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
4003 { "IOR::type_id", "giop.typeid",
4004 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4007 { &hf_giop_iiop_v_maj,
4008 { "IIOP Major Version", "giop.iiop_vmaj",
4009 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4012 { &hf_giop_iiop_v_min,
4013 { "IIOP Minor Version", "giop.iiop_vmin",
4014 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4017 { &hf_giop_endianess,
4018 { "Endianess", "giop.endianess",
4019 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4022 { &hf_giop_IIOP_tag,
4023 { "IIOP Component TAG", "giop.iioptag",
4024 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4028 { "IOR Profile TAG", "giop.iortag",
4029 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4033 { "TypeCode enum", "giop.TCKind",
4034 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4037 { &hf_giop_typecode_count,
4038 { "TypeCode count", "giop.tccount",
4039 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4042 { &hf_giop_typecode_default_used,
4043 { "default_used", "giop.tcdefault_used",
4044 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4047 { &hf_giop_typecode_digits,
4048 { "Digits", "giop.tcdigits",
4049 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4053 { &hf_giop_typecode_length,
4054 { "Length", "giop.tclength",
4055 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4058 { &hf_giop_typecode_max_length,
4059 { "Maximum length", "giop.tcmaxlen",
4060 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4063 { &hf_giop_typecode_member_name,
4064 { "TypeCode member name", "giop.tcmemname",
4065 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4068 { &hf_giop_typecode_name,
4069 { "TypeCode name", "giop.tcname",
4070 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4073 { &hf_giop_typecode_scale,
4074 { "Scale", "giop.tcscale",
4075 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4078 { &hf_giop_typecode_ValueModifier,
4079 { "ValueModifier", "giop.tcValueModifier",
4080 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4083 { &hf_giop_typecode_Visibility,
4084 { "Visibility", "giop.tcVisibility",
4085 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4090 { &hf_giop_type_boolean,
4091 { "TypeCode boolean data", "giop.tcboolean",
4092 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4095 { &hf_giop_type_char,
4096 { "TypeCode char data", "giop.tcchar",
4097 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4100 { &hf_giop_type_double,
4101 { "TypeCode double data", "giop.tcdouble",
4102 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4105 { &hf_giop_type_enum,
4106 { "TypeCode enum data", "giop.tcenumdata",
4107 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4111 * float as double ?? -- FIX
4114 { &hf_giop_type_float,
4115 { "TypeCode float data", "giop.tcfloat",
4116 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4119 { &hf_giop_type_long,
4120 { "TypeCode long data", "giop.tclongdata",
4121 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4124 { &hf_giop_type_octet,
4125 { "TypeCode octet data", "giop.tcoctet",
4126 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4129 { &hf_giop_type_short,
4130 { "TypeCode short data", "giop.tcshortdata",
4131 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4134 { &hf_giop_type_string,
4135 { "TypeCode string data", "giop.tcstring",
4136 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4139 { &hf_giop_type_ulong,
4140 { "TypeCode ulong data", "giop.tculongdata",
4141 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4144 { &hf_giop_type_ushort,
4145 { "TypeCode ushort data", "giop.tcushortdata",
4146 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4150 * IIOP Module - Chapter 15.10.2
4153 { &hf_giop_iiop_host,
4154 { "IIOP::Profile_host", "giop.iiop.host",
4155 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4159 { &hf_giop_iiop_port,
4160 { "IIOP::Profile_port", "giop.iiop.port",
4161 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4166 * IIOP ServiceContext
4169 { &hf_giop_iop_vscid,
4170 { "VSCID", "giop.iiop.vscid",
4171 FT_UINT32, BASE_HEX, NULL, 0xfffff000, "", HFILL }
4175 { &hf_giop_iop_scid,
4176 { "SCID", "giop.iiop.scid",
4177 FT_UINT32, BASE_HEX, NULL, 0x00000fff, "", HFILL }
4184 static gint *ett[] = {
4188 &ett_giop_cancel_request,
4189 &ett_giop_locate_request,
4190 &ett_giop_locate_reply,
4196 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4198 proto_register_field_array (proto_giop, hf, array_length (hf));
4199 proto_register_subtree_array (ett, array_length (ett));
4202 /* register init routine */
4204 register_init_routine( &giop_init); /* any init stuff */
4207 * Init the giop user module hash tables here, as giop users
4208 * will populate it via register_giop_user_module BEFORE my
4209 * own giop_init() is called.
4212 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4214 giop_module_keys = g_mem_chunk_new("giop_module_keys",
4215 sizeof(struct giop_module_key),
4216 giop_module_init_count * sizeof(struct giop_module_key),
4219 giop_module_vals = g_mem_chunk_new("giop_module_vals",
4220 sizeof(struct giop_module_val),
4221 giop_module_init_count * sizeof(struct giop_module_val),
4228 void proto_reg_handoff_giop (void) {
4229 heur_dissector_add("tcp", dissect_giop, proto_giop);
4238 * Ref Corba v2.4.2 Chapter 13
4246 typedef unsigned long ProfileId;
4248 const ProfileId TAG_INTERNET_IOP = 0;
4249 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4251 struct TaggedProfile {
4253 sequence <octet> profile_data;
4258 sequence <TaggedProfile> profiles;
4261 typedef unsigned long ComponentId;
4263 struct TaggedComponent {
4265 sequence <octet> component_data;
4268 typedef sequence <TaggedComponent> MultipleComponentProfile;
4274 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4275 guint32 boundary, gboolean stream_is_big_endian) {
4278 guint32 seqlen_p; /* sequence length of profiles */
4281 proto_tree *tree = NULL; /* IOR tree */
4284 gchar *repobuf = NULL; /* for repository ID */
4288 /* create a subtree */
4291 tf = proto_tree_add_text (ptree, tvb, *offset, tvb_length (tvb), "IOR");
4292 tree = proto_item_add_subtree (tf, ett_giop_ior);
4296 /* Get type_id == Repository ID */
4298 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4301 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4302 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4304 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4305 *offset-u_octet4,u_octet4,repobuf);
4310 /* g_free(repobuf); */ /* dont free yet, as must wait until I have */
4311 /* the object key before I can add both to hash */
4312 /* this is done later */
4314 /* Now get a sequence of profiles */
4315 /* Get sequence length (number of elements) */
4317 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4319 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4320 *offset-sizeof(seqlen_p),4,seqlen_p);
4324 /* fetch all TaggedProfiles in this sequence */
4326 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4327 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4332 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4333 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4335 guint32 seqlen_pd; /* sequence length of profile data */
4337 guint32 pidtag; /* profile ID TAG */
4339 gchar *profile_data = NULL; /* profile_data pointer */
4340 gchar *p_profile_data = NULL; /* printable profile_data pointer */
4342 guint32 new_boundary; /* for encapsulations encountered */
4343 gboolean new_big_endianess; /* for encapsulations encountered */
4345 /* Get ProfileId tag */
4347 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4350 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4351 *offset-sizeof(pidtag),4,pidtag);
4354 /* get sequence length, new endianness and boundary for encapsulation */
4356 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4357 stream_is_big_endian, boundary,
4358 &new_big_endianess, &new_boundary);
4360 /* return if zero length sequence */
4367 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4368 * decode it, otherwise just dump the octet sequence
4370 * also, store IOR in our objectkey hash
4372 * TODO - handle other TAGS
4376 case IOP_TAG_INTERNET_IOP:
4378 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4383 /* fetch all octets in this sequence */
4385 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd);
4387 /* Make a printable string */
4389 p_profile_data = make_printable_string( profile_data, seqlen_pd );
4392 proto_tree_add_text (tree, tvb, *offset -seqlen_pd, seqlen_pd,
4393 "Profile Data: %s", p_profile_data);
4399 g_free(profile_data);
4400 g_free(p_profile_data);
4407 * Decode IIOP IOR Profile
4408 * Ref Chap 15.7.2 in Corba Spec
4412 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4413 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4414 gboolean store_flag) {
4416 guint32 i; /* loop index */
4418 guint8 v_major,v_minor; /* IIOP sersion */
4420 guint32 u_octet4; /* u long */
4421 guint16 u_octet2; /* u short */
4422 guint32 seqlen; /* generic sequence length */
4423 guint32 seqlen1; /* generic sequence length */
4424 gchar *objkey = NULL; /* object key pointer */
4425 gchar *p_chars = NULL; /* printable characters pointer */
4428 /* Get major/minor version */
4430 v_major = get_CDR_octet(tvb,offset);
4431 v_minor = get_CDR_octet(tvb,offset);
4435 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4436 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4437 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4438 *offset-sizeof(v_minor),1,v_minor );
4444 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4447 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4448 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4450 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4451 *offset-u_octet4,u_octet4,buf);
4455 g_free(buf); /* dont forget */
4459 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4462 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4463 *offset-sizeof(u_octet2),2,u_octet2);
4467 /* Object Key - sequence<octet> object_key */
4469 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4472 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4473 *offset-sizeof(seqlen),4,seqlen);
4477 /* fetch all octets in this sequence */
4478 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4481 * Now we may have the Repository ID from earlier, as well
4482 * as the object key sequence and lengh. So lets store them in
4483 * our objectkey hash and free buffers.
4485 * But only insert if user is not clicking and repo id not NULL.
4491 if(!pinfo->fd->flags.visited)
4492 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4497 * No pinfo, but store anyway if flag set. eg: IOR read from file
4501 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4505 /* Make a printable string */
4507 p_chars = make_printable_string( objkey, seqlen );
4510 proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
4511 "Object Key: %s", p_chars);
4515 g_free(repo_id_buf);
4518 p_chars = NULL; /* reuse later */
4521 * Now see if if its v1.1 or 1.2, as they can contain
4522 * extra sequence of IOP::TaggedComponents
4535 /* sequence of IOP::TaggedComponents */
4536 /* Ref Chap 13 in Corba Spec */
4538 /* get sequence length */
4539 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4542 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4543 *offset-sizeof(seqlen),4,seqlen);
4546 for (i=0; i< seqlen; i++) {
4548 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4550 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4551 *offset-sizeof(u_octet4),4,u_octet4);
4554 /* get component_data */
4555 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4557 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4558 *offset-sizeof(seqlen1),4,seqlen1);
4562 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4565 /* Make a printable string of data */
4567 p_chars = make_printable_string(buf, seqlen1);
4569 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4570 "component_data: %s", p_chars);
4577 buf = NULL; /* reuse later */
4578 p_chars = NULL; /* reuse later */
4586 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4594 * Service Contexts Begin
4602 void dissect_SID_BI_DIR_IIOP(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4603 MessageHeader *header, gchar *operation, guint32 boundary) {
4613 * Service Contexts End
4625 * typedef unsigned long ServiceID;
4627 * struct ServiceContext {
4628 * ServiceID context_id;
4629 * sequence <octet> context_data;
4631 * typedef sequence <ServiceContext> ServiceContextList;
4634 * Note: Spec says context_data is an encapsulation.
4641 void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4642 gboolean stream_is_be, guint32 boundary) {
4644 guint32 seqlen; /* sequence length */
4645 guint32 seqlen_cd; /* sequence length, context_data */
4647 proto_tree *tree = NULL; /* ServiceContext tree */
4651 gchar *context_data = NULL;
4652 gchar *p_context_data = NULL;
4655 guint32 vscid; /* Vendor Service context id */
4658 /* create a subtree */
4661 tf = proto_tree_add_text (ptree, tvb, *offset, tvb_length (tvb), "ServiceContextList");
4662 tree = proto_item_add_subtree (tf, ett_giop_scl);
4665 /* Get sequence length (number of elements) */
4667 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4669 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4670 *offset-sizeof(seqlen),4,seqlen);
4673 /* return if zero length sequence */
4678 /* Loop for all ServiceContext's */
4680 for (i=0; i<seqlen; i++) {
4682 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4684 proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4685 *offset-sizeof(context_id),4,context_id);
4687 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4688 *offset-sizeof(context_id),4,context_id);
4692 vscid = context_id && 0xfffff000; /* vendor info, top 20 bits */
4693 scid = context_id && 0x00000fff; /* standard service info, lower 12 bits */
4696 #if CONTEXT_DATA_IS_ENCAPSULATED
4698 /* get sequence length, new endianness and boundary for encapsulation */
4700 seqlen_cd = get_CDR_encap_info(tvb, tree, offset,
4701 stream_is_be, boundary,
4702 &new_big_endianess, &new_boundary);
4706 /* get sequence length, and NO encapsulation */
4708 seqlen_cd = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4712 /* return if zero length sequence */
4718 * Now decode sequence according to vendor ServiceId, but I dont
4719 * have that yet, so just dump it as data.
4722 /* fetch all octets in this sequence */
4724 get_CDR_octet_seq(tvb, &context_data, offset, seqlen_cd);
4726 /* Make a printable string */
4728 p_context_data = make_printable_string( context_data, seqlen_cd );
4731 proto_tree_add_text (tree, tvb, *offset - seqlen_cd , seqlen_cd,
4732 "context_data: %s", p_context_data);
4735 g_free(context_data);
4736 g_free(p_context_data);
4741 return; /* for now, fix later */
4746 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
4749 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
4750 gboolean stream_is_big_endian,
4753 guint32 length; /* string length */
4754 guint32 minor_code_value;
4755 guint32 completion_status;
4757 gchar *buf = NULL; /* pointer to string buffer */
4759 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
4762 proto_tree_add_text(tree, tvb, *offset-4, 4,
4763 "Exception length: %u", length);
4765 proto_tree_add_text(tree, tvb, *offset - length, length,
4766 "Exception id: %s", buf );
4770 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4771 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4774 proto_tree_add_text(tree, tvb, *offset-8, 4,
4775 "Minor code value: %u", minor_code_value);
4776 proto_tree_add_text(tree, tvb, *offset-4, 4,
4777 "Completion Status: %u", completion_status);
4783 * Helper functions for dissecting TypeCodes
4785 * These functions decode the complex parameter lists
4786 * of TypeCodes as defined in the CORBA spec chapter 15.
4789 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4790 gboolean stream_is_big_endian, guint32 boundary,
4791 MessageHeader * header) {
4793 guint32 new_boundary; /* new boundary for encapsulation */
4794 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4796 guint32 seqlen; /* sequence length */
4798 /* get sequence length, new endianness and boundary for encapsulation */
4799 seqlen = get_CDR_encap_info(tvb, tree, offset,
4800 stream_is_big_endian, boundary,
4801 &new_stream_is_big_endian, &new_boundary);
4803 /* get repository ID */
4804 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4808 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4809 hf_giop_typecode_name);
4814 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4815 gboolean stream_is_big_endian, guint32 boundary,
4816 MessageHeader * header ) {
4818 guint32 new_boundary; /* new boundary for encapsulation */
4819 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4821 guint32 count; /* parameter count (of tuples) */
4822 guint32 seqlen; /* sequence length */
4823 guint32 i; /* loop index */
4825 /* get sequence lengt,h new endianness and boundary for encapsulation */
4826 seqlen = get_CDR_encap_info(tvb, tree, offset,
4827 stream_is_big_endian, boundary,
4828 &new_stream_is_big_endian, &new_boundary);
4830 /* get repository ID */
4831 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4835 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4836 hf_giop_typecode_name);
4838 /* get count of tuples */
4839 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4841 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4842 *offset-sizeof(count),4,count);
4845 /* get all tuples */
4846 for (i=0; i< count; i++) {
4847 /* get member name */
4848 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4849 hf_giop_typecode_member_name);
4851 /* get member type */
4852 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4858 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4859 gboolean stream_is_big_endian, guint32 boundary,
4860 MessageHeader * header) {
4862 guint32 new_boundary; /* new boundary for encapsulation */
4863 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4865 guint32 TCKind; /* TypeCode */
4866 gint32 s_octet4; /* signed int32 */
4868 guint32 count; /* parameter count (of tuples) */
4869 guint32 seqlen; /* sequence length */
4870 guint32 i; /* loop index */
4872 /* get sequence legnth, new endianness and boundary for encapsulation */
4873 seqlen = get_CDR_encap_info(tvb, tree, offset,
4874 stream_is_big_endian, boundary,
4875 &new_stream_is_big_endian, &new_boundary);
4877 /* get repository ID */
4878 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4882 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4883 hf_giop_typecode_name);
4885 /* get discriminant type */
4886 TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4888 /* get default used */
4889 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
4891 proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
4892 *offset-sizeof(s_octet4),4,s_octet4);
4894 /* get count of tuples */
4895 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4897 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4898 *offset-sizeof(count),4,count);
4901 /* get all tuples */
4902 for (i=0; i< count; i++) {
4903 /* get label value, based on TCKind above */
4904 dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
4906 /* get member name */
4907 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4908 hf_giop_typecode_member_name);
4910 /* get member type */
4911 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4917 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4918 gboolean stream_is_big_endian, guint32 boundary,
4919 MessageHeader * header) {
4921 guint32 new_boundary; /* new boundary for encapsulation */
4922 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4924 guint32 count; /* parameter count (of tuples) */
4925 guint32 seqlen; /* sequence length */
4926 guint32 i; /* loop index */
4928 /* get sequence length, new endianness and boundary for encapsulation */
4929 seqlen = get_CDR_encap_info(tvb, tree, offset,
4930 stream_is_big_endian, boundary,
4931 &new_stream_is_big_endian, &new_boundary);
4933 /* get repository ID */
4934 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4938 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4939 hf_giop_typecode_name);
4941 /* get count of tuples */
4942 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4944 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4945 *offset-sizeof(count),4,count);
4948 /* get all tuples */
4949 for (i=0; i< count; i++) {
4950 /* get member name */
4951 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4952 hf_giop_typecode_member_name);
4958 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4959 gboolean stream_is_big_endian, guint32 boundary,
4960 MessageHeader * header) {
4962 guint32 new_boundary; /* new boundary for encapsulation */
4963 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4965 guint32 u_octet4; /* unsigned int32 */
4967 guint32 seqlen; /* sequence length */
4969 /* get sequence length, new endianness and boundary for encapsulation */
4970 seqlen = get_CDR_encap_info(tvb, tree, offset,
4971 stream_is_big_endian, boundary,
4972 &new_stream_is_big_endian, &new_boundary);
4974 /* get element type */
4975 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4977 /* get max length */
4978 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4980 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
4981 *offset-sizeof(u_octet4),4,u_octet4);
4986 static void dissect_tk_array_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 u_octet4; /* unsigned int32 */
4995 guint32 seqlen; /* sequence length */
4997 /* get sequence length, new endianness and boundary for encapsulation */
4998 seqlen = get_CDR_encap_info(tvb, tree, offset,
4999 stream_is_big_endian, boundary,
5000 &new_stream_is_big_endian, &new_boundary);
5002 /* get element type */
5003 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5006 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5008 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5009 *offset-sizeof(u_octet4),4,u_octet4);
5014 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5015 gboolean stream_is_big_endian, guint32 boundary,
5016 MessageHeader * header) {
5018 guint32 new_boundary; /* new boundary for encapsulation */
5019 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5021 guint32 seqlen; /* sequence length */
5023 /* get sequence legnth, new endianness and boundary for encapsulation */
5024 seqlen = get_CDR_encap_info(tvb, tree, offset,
5025 stream_is_big_endian, boundary,
5026 &new_stream_is_big_endian, &new_boundary);
5028 /* get repository ID */
5029 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5033 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5034 hf_giop_typecode_name);
5036 /* get ??? (noname) TypeCode */
5037 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5042 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5043 gboolean stream_is_big_endian, guint32 boundary,
5044 MessageHeader * header) {
5046 guint32 new_boundary; /* new boundary for encapsulation */
5047 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5049 guint32 count; /* parameter count (of tuples) */
5050 guint32 seqlen; /* sequence length */
5051 guint32 i; /* loop index */
5053 /* get sequence length, new endianness and boundary for encapsulation */
5054 seqlen = get_CDR_encap_info(tvb, tree, offset,
5055 stream_is_big_endian, boundary,
5056 &new_stream_is_big_endian, &new_boundary);
5058 /* get repository ID */
5059 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5063 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5064 hf_giop_typecode_name);
5066 /* get count of tuples */
5067 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5069 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5070 *offset-sizeof(count),4,count);
5073 /* get all tuples */
5074 for (i=0; i< count; i++) {
5075 /* get member name */
5076 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5077 hf_giop_typecode_member_name);
5079 /* get member type */
5080 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5086 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5087 gboolean stream_is_big_endian, guint32 boundary,
5088 MessageHeader * header) {
5090 guint32 new_boundary; /* new boundary for encapsulation */
5091 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5093 gint16 s_octet2; /* signed int16 */
5095 guint32 count; /* parameter count (of tuples) */
5096 guint32 seqlen; /* sequence length */
5097 guint32 i; /* loop index */
5099 /* get sequence length, new endianness and boundary for encapsulation */
5100 seqlen = get_CDR_encap_info(tvb, tree, offset,
5101 stream_is_big_endian, boundary,
5102 &new_stream_is_big_endian, &new_boundary);
5104 /* get repository ID */
5105 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5109 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5110 hf_giop_typecode_name);
5112 /* get ValueModifier */
5113 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5115 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5116 *offset-sizeof(s_octet2),2,s_octet2);
5119 /* get conrete base */
5120 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5122 /* get count of tuples */
5123 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5125 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5126 *offset-sizeof(count),4,count);
5129 /* get all tuples */
5130 for (i=0; i< count; i++) {
5131 /* get member name */
5132 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5133 hf_giop_typecode_member_name);
5135 /* get member type */
5136 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5138 /* get Visibility */
5139 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5141 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5142 *offset-sizeof(s_octet2),2,s_octet2);
5149 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5150 gboolean stream_is_big_endian, guint32 boundary,
5151 MessageHeader * header) {
5153 guint32 new_boundary; /* new boundary for encapsulation */
5154 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5156 guint32 seqlen; /* sequence length */
5158 /* get sequence length, new endianness and boundary for encapsulation */
5159 seqlen = get_CDR_encap_info(tvb, tree, offset,
5160 stream_is_big_endian, boundary,
5161 &new_stream_is_big_endian, &new_boundary);
5163 /* get repository ID */
5164 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5168 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5169 hf_giop_typecode_name);
5171 /* get ??? (noname) TypeCode */
5172 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5176 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5177 gboolean stream_is_big_endian, guint32 boundary,
5178 MessageHeader * header) {
5180 guint32 new_boundary; /* new boundary for encapsulation */
5181 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5183 guint32 seqlen; /* sequence length */
5185 /* get sequence length, new endianness and boundary for encapsulation */
5186 seqlen = get_CDR_encap_info(tvb, tree, offset,
5187 stream_is_big_endian, boundary,
5188 &new_stream_is_big_endian, &new_boundary);
5190 /* get repository ID */
5191 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5195 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5196 hf_giop_typecode_name);
5201 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5202 gboolean stream_is_big_endian, guint32 boundary,
5203 MessageHeader * header) {
5205 guint32 new_boundary; /* new boundary for encapsulation */
5206 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5208 guint32 seqlen; /* sequence length */
5210 /* get sequence length, new endianness and boundary for encapsulation */
5211 seqlen = get_CDR_encap_info(tvb, tree, offset,
5212 stream_is_big_endian, boundary,
5213 &new_stream_is_big_endian, &new_boundary);
5215 /* get repository ID */
5216 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5220 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5221 hf_giop_typecode_name);
5225 /* Typecode parameter lists are encoded as encapsulations and
5226 * this function gets the encapsulation information; see
5227 * CORBA spec chapter 15
5230 * Renamed to get_CDR_encap_info() for any encapsulation
5231 * we come across, useful helper function
5233 * Also, should return immediately if seqlen == 0.
5234 * ie: Forget about trying to grab endianess for
5235 * zero length sequence.
5237 * Caller must always check seqlen == 0, and not assume its value
5240 * Note: there seemed to be considerable confusion in corba
5241 * circles as to the correct interpretation of encapsulations,
5242 * and zero length sequences etc, but this is our best bet at the
5249 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5250 gboolean old_stream_is_big_endian, guint32 old_boundary,
5251 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5253 guint32 seqlen; /* sequence length */
5254 guint8 giop_endianess;
5256 /* Get sequence length of parameter list */
5257 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5259 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5260 *offset-sizeof(seqlen),4,seqlen);
5266 * seqlen == 0, implies no endianess and no data
5267 * so just return. Populate new_boundary_ptr and
5268 * new_stream_is_big_endian_ptr with current (old)
5269 * values, just to keep everyone happy. -- FS
5275 *new_boundary_ptr = old_boundary;
5276 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5282 /* Start of encapsulation of parameter list */
5283 *new_boundary_ptr = *offset; /* remember */
5284 giop_endianess = get_CDR_octet(tvb,offset);
5286 *new_stream_is_big_endian_ptr = ! giop_endianess;
5289 * Glib: typedef gint gboolean;
5290 * ie: It is not a guint8, so cannot use sizeof to correctly
5296 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5297 *offset-1,1,giop_endianess);
5307 * gets a TypeCode complex string parameter and
5308 * displays it in the relevant tree.
5311 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5312 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5314 guint32 u_octet4; /* unsigned int32 */
5315 gchar *buf = NULL; /* ptr to string buffer */
5318 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5321 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5322 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5324 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5328 g_free(buf); /* dont forget */
5333 * For a given data type, given by a TypeCode gets the associated data
5334 * and displays it in the relevant tree.
5337 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5338 gboolean stream_is_big_endian, guint32 boundary,
5339 MessageHeader * header, guint32 data_type ) {
5341 gboolean my_boolean; /* boolean */
5343 gint8 s_octet1; /* signed int8 */
5344 guint8 u_octet1; /* unsigned int8 */
5346 gint16 s_octet2; /* signed int16 */
5347 guint16 u_octet2; /* unsigned int16 */
5349 gint32 s_octet4; /* signed int32 */
5350 guint32 u_octet4; /* unsigned int32 */
5352 gdouble my_double; /* double */
5353 gfloat my_float; /* float */
5355 gchar *buf = NULL; /* ptr to string buffer */
5357 /* Grab the data according to data type */
5359 switch (data_type) {
5361 /* nothing to decode */
5364 /* nothing to decode */
5367 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5369 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5370 *offset-sizeof(s_octet2),2,s_octet2);
5374 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5376 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5377 *offset-sizeof(s_octet4),4,s_octet4);
5381 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5383 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5384 *offset-sizeof(u_octet2),2,u_octet2);
5388 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5390 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5391 *offset-sizeof(u_octet4),4,u_octet4);
5395 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5397 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5398 *offset-sizeof(my_float),4,my_float);
5402 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5404 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5405 *offset-sizeof(my_double),8,my_double);
5409 my_boolean = get_CDR_boolean(tvb,offset);
5411 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5412 *offset-1,1,my_boolean);
5416 u_octet1 = get_CDR_char(tvb,offset);
5418 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5419 *offset-sizeof(u_octet1),1,u_octet1);
5423 u_octet1 = get_CDR_octet(tvb,offset);
5425 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5426 *offset-sizeof(u_octet1),1,u_octet1);
5430 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5433 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5444 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5446 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5447 *offset-sizeof(u_octet4),4,u_octet4);
5451 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5453 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5454 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5456 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5457 *offset-u_octet4,u_octet4,buf);
5461 g_free(buf); /* dont forget */
5478 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5480 if (s_octet1 < 0) { /* no size to add to tree */
5481 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5482 *offset+s_octet1,(-s_octet1),buf);
5484 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5485 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5486 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5487 *offset-s_octet1,s_octet1,buf);
5491 g_free(buf); /* dont forget */
5494 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5496 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5497 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5498 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5499 *offset-u_octet4,u_octet4,buf);
5502 g_free(buf); /* dont forget */
5512 case tk_abstract_interface:
5515 g_warning("giop: Unknown typecode data type %u \n", data_type);