2 * Routines for CORBA GIOP/IIOP packet disassembly
5 * Laurent Deniel <laurent.deniel@free.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.65 2003/01/26 19:35:24 deniel Exp $
14 * Ethereal - Network traffic analyzer
15 * By Gerald Combs <gerald@ethereal.com>
16 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 * 1. heuristic giop dissector table [started]
37 * 2. GUI options, see 20
38 * 3. Remove unneccessary reply_status in heuristic dissector calls (now
39 * part of MessageHeader) [done]
40 * 4. get_CDR_xxx should be passed an alignment offset value
41 * rather than GIOP_HEADER_SIZE, as alignment can also change in a
42 * octet stream when eg: encapsulation is used [done]
43 * 5. GIOP users should eventually get there own tvbuff, and
44 * not rely on the GIOP tvbuff, more robust
45 * 6. get_CDR_string,wchar,wstring etc should handle different
46 * GIOP versions [started]
47 * 7. Fix situation where req_id is not unique in a logfile [done, use FN/MFN, needs improving.]
49 * 8. Keep request_1_2 in step with request_1_1 [started]
50 * 9. Explicit module name dissection [done]
51 * 10. Decode IOR and put in a useful struct [IOR decode started]
52 * 11. Fix encapsulation of IOR etc and boundary [done]
53 * 12. handle get_CDR_typeCode() [started]
54 * 13. Handle different IOR profiles
55 * 14. Change printable_string to RETURN a new string, not to modify the old.
56 * or, new function, make_printable_string [done, make_printable_string]
58 * 15. Handle "TCKind", and forget about eg: enum translation to symbolic values
59 * otherwise need knowledge of sub dissectors data - YUK [done]
60 * 16. Handle multiple RepoId representations, besides IDL:Echo:1.0 (see 13.)
61 * 17. Pass subset of RepoID to explicit dissector.
62 * eg : If IDL:Mod1/Mod2/Int3:1.0 then pass "Mod1/Mode2/Int3" to sub dissector[done]
63 * 18. Better hashing algorithms
64 * 19. Handle hash collision properly .
65 * 20. Allow users to paste a stringified IOR into the GUI, and tie it
67 * 21. Add complete_request_packet_list and complete_reply_packet_hash.[done]
68 * 22. Handle case where users click in any order, AND try and match
69 * REPLY msg to the correct REQUEST msg when we have a request_id collision.[done]
70 * 23. Clean up memory management for all those g_malloc's etc
71 * 24. register_giop_user_module could return a key for every distinct Module/Interface
72 * the sub_dissector uses. So, instead of strcmp()'s when handling the
73 * namespace of an operation, we could have a lookup table instead.
74 * 25. A few typedefs in the right place.
75 * 26 Improve handling of gchar * and use const gchar * where possible.
76 * 27. Read/write IOR etc to/from file, allows objkey hash to be built from
77 * external data [read done, write incomplete]
78 * 28. Call sub dissector only if tvb_offset_exists(). [Done, this is checked
79 * inside try_explicit_giop_dissector() ]
81 * 29. Make add/delete routine for objkey hash as it may be useful when say reading
82 * stringified IOR's from a file to add them to our hash. ie: There are other ways
83 * to populate our object key hash besides REPLY's to RESOLVE(request) [done]
85 * 30. Add routine to encode/decode stringified IOR's [decode done]
86 * 31. Add routine to read IOR's from file [done]
87 * 32. TypeCode -none-, needs decoding.
88 * 33. Complete dissect_data_for_typecode.
89 * 34. For complex TypeCodes need to check final offset against original offset + sequence length.
90 * 35. Update REQUEST/REPLY 1_2 according to IDL (eg; ServiceContextList etc).
91 * 36. Adding decode_ServiceContextList, incomplete.
92 * 37. Helper functions should not ALWAYS rely on header to find current endianess. It should
93 * be passed from user, eg Use stream_is_big_endian. [started]
94 * 38. Remove unwanted/unused function parameters, see decode_IOR [started]
95 * 40. Add sequence <IOP::TaggedComponent> components to IIOP IOR profile. Perhaps
96 * decode_IOP_TaggedComponents as a helper function. [done - NOT helper]
98 * 41. Make important field searchable from Message header. ie: Remove add_text_
99 * 42. Use sub-tree for decode_ServiceContextList, looks better.
100 * 43. dissect_reply_body, no exception dissector calls
101 * - call subdiss directly, as we already have handle.
102 * - add repoid to heuristic call also.
104 * 44. typedef using xxx_t in .h file.
105 * 45. Subdissectors should not be passed MessageHeader to find endianness and
106 * version, they should be passed directly ?
107 * 46. get_CDR_wchar and wstring need wide chars decoded (just dumped in
108 * any readable form at present, not handled well at all, suggestions welcome -- FS
109 * 47. Change ...add_text to ...add_xxx (ie use hf fields).
111 * 48. BUG - file load with a GIOP filter set, causes the FN/MFN data struct to be
112 * not initiated properly. Hit "Reload" as a workaround, til I fix this -- FS
119 * Intended Decode strategy:
120 * =========================
124 * REQUEST: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
125 * and populate complete_request_packet_hash
127 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
132 * REQUEST: FN -> giop_sub_handle_t directly (via complete_request_packet_hash)
134 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
135 * (via complete_request_packet_hash
141 * 1. Request_ID's are unique only per connection.
143 * 2. You must be monitoring the network when the client does
144 * a REQUEST(resolve), otherwise I have no knowledge of the
145 * association between object_key and REPOID. I could talk to
146 * a Nameserver, but then I would start "generating" packets.
147 * This is probably not a good thing for a protocol analyser.
148 * Also, how could I decode logfiles offline.
150 * TODO -- Read stringified IORs from an input file.[done]
152 * 3. User clicks (REQUEST) is currently handle the same as
153 * the initial pass handling.
155 * ie: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
160 * Important Data Structures:
165 * This is a hash table that maps IDL Module/Interface Names (Key)
166 * to sub_dissector handles, giop_sub_handle_t. It is populated
167 * by subdissectors, via register_giop_user_module(). This
168 * table is used when we have a REPOID, and explicitly wish to
169 * call the subdissector that has registered responsibility for
170 * that IDL module/interface.
176 * This singly linked list is used to hold entries for
177 * heuristic based subdissectors. It is populated by sub_dissectors
178 * wishing to be called via heuristic mechanisms. They do this
179 * via the register_giop_user() function.
185 * This hash table maps object_key's (key) onto REPOID's (val).
186 * Once a client has REQUEST(resolve) an object , it knows about
187 * an object (interface) via its object_key (see IOR). So in order to follow
188 * packets that contain an object_key only, and to be able to forward it
189 * to the correct explicit subdissector, we need this table.
191 * So, I listen in on REQUEST(resolve) messages between client and
192 * Nameserver, and store the respones (REPLY/Objkey,Repo_ID) here.
194 * Also, stringified IOR's can be read from a file "IOR.txt" and used
195 * to populate this hash also.
198 * Other Data structures
199 * =======================
201 * These structures have been added to minimise the possibility
202 * of incorrectly interpreted packets when people click all
203 * over the place, in no particular order, when the request_id's are
204 * not unique as captured. If all request_is'd are unique, as captured, then
205 * we would not have to deal with this problem.
208 * When the logfile or packets are initially being processed, I will
209 * build 2 structures. The intent is to be able to map a REPLY message
210 * back to the most recent REQUEST message with the same Request_ID
211 * (TODO and matching port and IP address ??)
217 * MFN - Matching Frame Number
220 * complete_request_packet_list
221 * ----------------------------
223 * This is a list that contains ALL the FN's that are REQUEST's, along with
224 * operation,request_id and giop_sub_handle_t
226 * complete_reply_packet_hash
227 * --------------------------
229 * This is a hash table. It is populated with FN (key) and MFN (val).
230 * This allows me to handle the case, where if you click on any REPLY
231 * message, I can lookup the matching request. This can improve
232 * the match rate between REQUEST and REPLY when people click in
233 * any old fashion, but is NOT foolproof.
235 * The algorithm I use to populate this hash during initial pass,
238 * If packet is a REPLY, note the reqid, and then traverse backwards
239 * through the complete_request_packet_list from its tail, looking
240 * for a FN that has the same Request_id. Once found, take the found FN
241 * from complete_reply_packet_hash, and insert it into the MFN field
242 * of the complete_reply_packet_hash.
245 * See TODO for improvements to above algorithm.
247 * So now when people click on a REQUEST packet, I can call lookup the
248 * giop_sub_handle_t directly from complete_request_packet_list.
250 * And, when they click on a REPLY, I grab the MFN of this FN from
251 * complete_reply_packet_hash, then look that up in the complete_request_packet_list
252 * and call the sub_dissector directly.
254 * So, how do I differentiate between the initial processing of incoming
255 * packets, and a user clickin on one ? Good question.
257 * I leverage the pinfo_fd->flags.visited on a per frame
260 * To quote from the ever helpful development list
262 * " When a capture file is initially loaded, all "visited" flags
263 * are 0. Ethereal then makes the first pass through file,
264 * sequentially dissecting each packet. After the packet is
265 * dissected the first time, "visited" is 1. (See the end of
266 * dissect_packet() in epan/packet.c; that's the code that
267 * sets "visited" to 1).
269 * By the time a user clicks on a packet, "visited" will already
270 * be 1 because Ethereal will have already done its first pass
271 * through the packets.
273 * Reload acts just like a normal Close/Open, except that it
274 * doesn't need to ask for a filename. So yes, the reload button
275 * clears the flags and re-dissects the file, just as if the file
276 * had been "opened". "
291 #ifdef NEED_STRERROR_H
292 #include "strerror.h"
295 #include <epan/packet.h>
296 #include "packet-giop.h"
299 * This affects how we handle context_data inside ServiceContext structs.
300 * According to CORBA 2.4.2, Context data is encapsulated in octet sequences,
301 * but so far I haven't seen the that on the wire. But, maybe its me -- FS
305 #define CONTEXT_DATA_IS_ENCAPSULATED 0
309 * Set to 1 for DEBUG output - TODO make this a runtime option
317 * ------------------------------------------------------------------------------------------+
318 * Private Helper function Declarations
319 * ------------------------------------------------------------------------------------------+
323 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
324 guint32 boundary, gboolean new_endianess, gchar *repobuf,
325 gboolean store_flag);
327 static void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *tree, int *offset,
328 gboolean stream_is_be, guint32 boundary);
330 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
331 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf);
333 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
334 guint32 boundary, gboolean stream_is_big_endian );
336 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
337 gboolean stream_is_big_endian,
340 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
341 gboolean stream_is_big_endian, guint32 boundary);
343 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
344 gboolean stream_is_big_endian, guint32 boundary,
345 MessageHeader * header);
347 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
348 gboolean stream_is_big_endian, guint32 boundary,
349 MessageHeader * header );
351 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
352 gboolean stream_is_big_endian, guint32 boundary);
354 static void dissect_tk_sequence_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_array_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_alias_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_except_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_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
371 gboolean stream_is_big_endian, guint32 boundary,
372 MessageHeader * header);
374 static void dissect_tk_value_box_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_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
379 gboolean stream_is_big_endian, guint32 boundary);
381 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
382 gboolean stream_is_big_endian, guint32 boundary);
385 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
386 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
388 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
389 gboolean stream_is_big_endian, guint32 boundary,
390 MessageHeader * header, guint32 data_type );
396 * ------------------------------------------------------------------------------------------+
397 * Data/Variables/Structs
398 * ------------------------------------------------------------------------------------------+
402 static int proto_giop = -1;
403 static int hf_giop_message_type = -1;
404 static int hf_giop_message_size = -1;
405 static int hf_giop_repoid = -1;
406 static int hf_giop_string_length = -1;
407 static int hf_giop_sequence_length = -1;
408 static int hf_giop_profile_id = -1;
409 static int hf_giop_type_id = -1;
410 static int hf_giop_iiop_v_maj = -1;
411 static int hf_giop_iiop_v_min = -1;
412 static int hf_giop_endianess = -1; /* esp encapsulations */
413 static int hf_giop_IOR_tag = -1;
414 static int hf_giop_IIOP_tag = -1;
416 static int hf_giop_TCKind = -1;
417 static int hf_giop_typecode_count = -1;
418 static int hf_giop_typecode_default_used = -1;
419 static int hf_giop_typecode_digits = -1;
420 static int hf_giop_typecode_length = -1;
421 static int hf_giop_typecode_max_length = -1;
422 static int hf_giop_typecode_member_name = -1;
423 static int hf_giop_typecode_name = -1;
424 static int hf_giop_typecode_scale = -1;
425 static int hf_giop_typecode_ValueModifier = -1;
426 static int hf_giop_typecode_Visibility = -1;
428 static int hf_giop_type_boolean = -1;
429 static int hf_giop_type_char = -1;
430 static int hf_giop_type_double = -1;
431 static int hf_giop_type_enum = -1;
432 static int hf_giop_type_float = -1;
433 static int hf_giop_type_long = -1;
434 static int hf_giop_type_octet = -1;
435 static int hf_giop_type_short = -1;
436 static int hf_giop_type_string = -1;
437 static int hf_giop_type_ulong = -1;
438 static int hf_giop_type_ushort = -1;
440 static int hf_giop_iiop_host = -1;
441 static int hf_giop_iiop_port = -1;
442 static int hf_giop_iop_vscid = -1;
443 static int hf_giop_iop_scid = -1;
449 static gint ett_giop = -1;
450 static gint ett_giop_reply = -1;
451 static gint ett_giop_request = -1;
452 static gint ett_giop_cancel_request = -1;
453 static gint ett_giop_locate_request = -1;
454 static gint ett_giop_locate_reply = -1;
455 static gint ett_giop_fragment = -1;
457 static gint ett_giop_scl = -1; /* ServiceContextList */
458 static gint ett_giop_ior = -1; /* IOR */
460 static dissector_handle_t data_handle;
463 static const value_string giop_endianess_vals[] = {
464 { 0x0, "Big Endian" },
465 { 0x1, "Little Endian" },
469 static const value_string sync_scope[] = {
470 { 0x0, "SYNC_NONE" },
471 { 0x1, "SYNC_WITH_TRANSPORT"},
472 { 0x2, "SYNC_WITH_SERVER"},
473 { 0x3, "SYNC_WITH_TARGET"},
479 static const value_string profile_id_vals[] = {
480 { 0x0, "TAG_INTERNET_IOP" },
481 { 0x1, "TAG_MULTIPLE_COMPONENTS"},
482 { 0x2, "TAG_SCCP_IOP"},
486 static const value_string giop_message_types[] = {
489 { 0x2, "CancelRequest"},
490 { 0x3, "LocateRequest"},
491 { 0x4, "LocateReply"},
492 { 0x5, "CloseConnection"},
493 { 0x6, "MessageError"},
498 static const value_string giop_locate_status_types[] = {
499 { 0x0, "Unknown Object" },
500 { 0x1, "Object Here"},
501 { 0x2, "Object Forward"},
502 { 0x3, "Object Forward Perm"},
503 { 0x4, "Loc System Exception"},
504 { 0x5, "Loc Needs Addressing Mode"},
508 static const value_string tckind_vals[] = {
521 { 12, "tk_TypeCode"},
522 { 13, "tk_Principal"},
528 { 19, "tk_sequence"},
532 { 23, "tk_longlong"},
533 { 24, "tk_ulonglong"},
534 { 25, "tk_longdouble"},
539 { 30, "tk_value_box"},
541 { 32, "tk_abstract_interface"},
547 #define GIOP_MAGIC "GIOP"
550 * TAGS for IOR Profiles
552 * Chapter 13 Corba 2.4.2
556 #define IOP_TAG_INTERNET_IOP 0
557 #define IOP_TAG_MULTIPLE_COMPONENTS 1
560 /* Max Supported versions */
562 static const guint GIOP_MAJOR = 1;
563 static const guint GIOP_MINOR = 2;
566 static const int KeyAddr = 0;
567 static const int ProfileAddr = 1;
568 static const int ReferenceAddr = 2;
572 static const value_string reply_status_types[] = {
573 { NO_EXCEPTION, "No Exception" } ,
574 { USER_EXCEPTION, "User Exception" } ,
575 { SYSTEM_EXCEPTION, "System Exception" } ,
576 { LOCATION_FORWARD, "Location Forward" } ,
577 { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
578 { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
584 typedef enum LocateStatusType
589 OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
590 LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
591 LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
595 typedef struct LocateReplyHeader
598 guint32 locate_status;
604 * DATA - complete_request_list
607 static GList *giop_complete_request_list;
609 struct comp_req_list_entry {
610 guint32 fn; /* frame number */
611 gchar * operation; /* echo echoString */
612 giop_sub_handle_t *subh; /* handle to sub dissector */
613 guint32 reqid; /* request id */
614 gchar * repoid; /* repository ID */
617 typedef struct comp_req_list_entry comp_req_list_entry_t;
621 * DATA - complete_reply_hash
623 * Maps reply FN to request MFN
626 static int complete_reply_hash_count = 1000; /* storage size for our permanent data */
627 /* ie: 1000 entries -- needs tweaking -- FS */
629 struct complete_reply_hash_key {
630 guint32 fn; /* reply frame number */
633 struct complete_reply_hash_val {
634 guint32 mfn; /* matching frame number (request) */
637 GHashTable *giop_complete_reply_hash = NULL; /* hash */
638 GMemChunk *giop_complete_reply_keys = NULL; /* key storage */
639 GMemChunk *giop_complete_reply_vals = NULL; /* val storage */
643 * DATA - Module Hash stuff to store data from register_giop_user_module
645 * ie: module (or interface ?) name, and ptr to sub_dissector handle
647 * With this knowledge, we can call a sub dissector directly,
650 * objkey -> repoid -> sub_dissector via registered module/interface
655 static int giop_module_init_count = 100; /* storage size for our permanent data */
656 /* ie: 100 entries -- needs tweaking -- FS */
658 struct giop_module_key {
659 gchar *module; /* module (interface?) name */
662 struct giop_module_val {
663 giop_sub_handle_t *subh; /* handle to sub dissector */
666 GHashTable *giop_module_hash = NULL; /* hash */
667 GMemChunk *giop_module_keys = NULL; /* key storage */
668 GMemChunk *giop_module_vals = NULL; /* val storage */
672 * DATA - GSList to store list of function (dissector) pointers.
673 * for heuristic dissection.
677 static GSList *giop_sub_list = NULL;
680 * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
681 * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
683 * With this knowledge, we can call a sub dissector directly later
686 * objkey -> repoid -> sub_dissector via registered module/interface
688 * rather than heuristic calls that do not provide operation context.
689 * (unless we pass the RepoID for a given objkey -- hmmm)
694 * Interesting operation list, add more if you want to save
698 static const char giop_op_resolve[] = "resolve";
699 static const char giop_op_bind_new_context[] = "bind_new_context";
700 static const char giop_op_bind[] = "bind";
703 * Enums for interesting local operations, that we may need to monitor
704 * with their subsequent replies
709 request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
710 request_bind_new_context_op_val, /* bind_new_context */
711 request_bind_op_val, /* bind */
712 request_get_INIT_op_val, /* finding Nameserver */
718 * hash for mapping object keys onto object namespaces, so
719 * I can call the correct dissector.
725 * Where did I get the IOR from.
729 req_res = 0, /* REQUEST (resolve) */
730 file, /* stringified IOR' in a file */
734 typedef enum ior_src ior_src_t;
739 * Enums for my lists and hash's
742 enum collection_data {
743 cd_heuristic_users = 0,
746 cd_complete_request_list,
747 cd_complete_reply_hash
750 typedef enum collection_data collection_data_t;
754 static int giop_objkey_init_count = 100; /* storage size for our permanent data */
755 /* ie: 100 entries -- needs tweaking -- FS */
757 struct giop_object_key {
758 guint8 *objkey; /* ptr to object key */
759 guint32 objkey_len; /* length */
762 struct giop_object_val {
763 guint8 *repo_id; /* ptr to Repository ID string */
764 ior_src_t src; /* where did Iget this IOR from */
767 GHashTable *giop_objkey_hash = NULL; /* hash */
768 GMemChunk *giop_objkey_keys = NULL; /* key storage */
769 GMemChunk *giop_objkey_vals = NULL; /* val storage */
774 * ------------------------------------------------------------------------------------------+
775 * Private helper functions
776 * ------------------------------------------------------------------------------------------+
782 * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
785 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
786 GList * newlist_start;
787 comp_req_list_entry_t * entry = NULL;
790 entry = g_malloc(sizeof(comp_req_list_entry_t));
791 opn = g_strdup(op); /* duplicate operation for storage */
794 entry->reqid = reqid;
796 entry->operation = opn;
797 entry->repoid = NULL; /* dont have yet */
799 newlist_start = g_list_append (list, entry); /* append */
801 return newlist_start;
806 * Used to find an entry with matching Frame Number FN
807 * in the complete_request_list list.
810 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
812 GList * element; /* entry in list */
813 comp_req_list_entry_t * entry_ptr = NULL;
815 element = g_list_last(giop_complete_request_list); /* start from last */
817 while(element) { /* valid list entry */
818 entry_ptr = element->data; /* grab data pointer */
819 if (entry_ptr->fn == fn) { /* similar FN */
822 element = g_list_previous(element); /* try next previous */
825 return NULL; /* no match so return NULL */
830 * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
832 * Call this when you know a FN and matching giop_sub_handle_t and repoid
834 * This is done in say, try_explicit_dissector for example.
838 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
840 comp_req_list_entry_t * entry = NULL;
841 entry = find_fn_in_list(fn); /* grab FN data entry */
845 entry->repoid = g_strdup(repoid); /* copy and store */
853 /* giop_complete_reply_hash "EQUAL" Functions */
855 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
856 const struct complete_reply_hash_key *mk1 = (const struct complete_reply_hash_key *)v;
857 const struct complete_reply_hash_key *mk2 = (const struct complete_reply_hash_key *)w;
859 if (mk1->fn == mk2->fn) {
863 return 0; /* found differences */
866 /* giop_complete_reply_hash "HASH" Functions */
868 static guint32 complete_reply_hash_fn(gconstpointer v) {
869 guint32 val; /* init hash value */
870 const struct complete_reply_hash_key *key = (const struct complete_reply_hash_key *)v;
872 val = key->fn; /* simple and unique */
879 * Insert the FN and MFN together in our complete_reply_hash.
882 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
884 struct complete_reply_hash_key key, *new_key;
885 struct complete_reply_hash_val *val = NULL;
889 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
892 return; /* FN collision */
895 new_key = g_mem_chunk_alloc(giop_complete_reply_keys);
896 new_key->fn = fn; /* save FN */
898 val = g_mem_chunk_alloc(giop_complete_reply_vals);
899 val->mfn = mfn; /* and MFN */
901 g_hash_table_insert(giop_complete_reply_hash, new_key, val);
906 * Find the MFN values from a given FN key.
907 * Assumes the complete_reply_hash is already populated.
910 static guint32 get_mfn_from_fn(guint32 fn) {
912 struct complete_reply_hash_key key;
913 struct complete_reply_hash_val *val = NULL;
914 guint32 mfn = fn; /* save */
917 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
920 mfn = val->mfn; /* grab it */
923 return mfn; /* mfn or fn if not found */
928 * Attempt to find the MFN for this FN, and return it.
929 * Return MFN if found, or just FN if not. This is
930 * only used when we are building
933 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
935 GList * element; /* last entry in list */
936 comp_req_list_entry_t * entry_ptr = NULL;
938 /* Need Some pretty snappy code */
940 /* Loop back from current end of complete_request_list looking for */
941 /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
944 * As this routine is only called during initial pass of data,
945 * and NOT when a user clicks, it is ok to start from Current
946 * end of complete_request_list when searching for a match.
947 * As that list is bing populated in the same order as FN's
950 * Also, can make check for same reqid more detailed, but I start
951 * with reqid. Could add say port or address checks etc later ??
955 element = g_list_last(giop_complete_request_list); /* get last */
957 while(element) { /* valid list entry */
958 entry_ptr = element->data; /* grab data pointer */
959 if (entry_ptr->reqid == reqid) { /* similar reqid */
960 return entry_ptr->fn; /* return MFN */
962 element = g_list_previous(element); /* try next previous */
965 return fn; /* no match so return FN */
969 /* Module Hash "EQUAL" Functions */
971 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
972 const struct giop_module_key *mk1 = (const struct giop_module_key *)v;
973 const struct giop_module_key *mk2 = (const struct giop_module_key *)w;
975 if (strcmp(mk1->module, mk2->module) == 0) {
979 return 0; /* found differences */
982 /* Module Hash "HASH" Functions */
984 static guint32 giop_hash_module_hash(gconstpointer v) {
987 guint32 val = 0; /* init hash value */
989 const struct giop_module_key *key = (const struct giop_module_key *)v;
992 * Hmm, try this simple hashing scheme for now.
993 * ie: Simple summation, FIX later -- FS
998 len = strlen(key->module);
1000 for (i=0; i<len; i++) {
1001 val += (guint8) key->module[i];
1010 * ------------------------------------------------------------------------------------------+
1011 * Public Utility functions
1012 * ------------------------------------------------------------------------------------------+
1019 * Routine to allow giop users to register their sub dissector function, name, and
1020 * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1021 * value returned from their proto_register_protocol(), so we can enable/disbale it
1022 * through the GUI (edit protocols).
1024 * This is used by try_explicit_giop_dissector() to find the
1025 * correct sub-dissector.
1029 void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
1031 struct giop_module_key module_key, *new_module_key;
1032 struct giop_module_val *module_val = NULL;
1034 module_key.module = module; /* module name */
1036 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1039 return; /* module name collision */
1042 /* So, passed module name should NOT exist in hash at this point.*/
1045 printf("giop:register_module: Adding Module %s to module hash \n", module);
1046 printf("giop:register_module: Module sub dissector name is %s \n", name);
1049 new_module_key = g_mem_chunk_alloc(giop_module_keys);
1050 new_module_key->module = module; /* save Module or interface name from IDL */
1052 module_val = g_mem_chunk_alloc(giop_module_vals);
1054 module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
1056 module_val->subh->sub_name = name; /* save dissector name */
1057 module_val->subh->sub_fn = sub; /* save subdissector*/
1058 module_val->subh->sub_proto = sub_proto; /* save subdissector's proto_XXX value */
1060 g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1067 /* Object Key Hash "EQUAL" Functions */
1069 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1070 const struct giop_object_key *v1 = (const struct giop_object_key *)v;
1071 const struct giop_object_key *v2 = (const struct giop_object_key *)w;
1073 if (v1->objkey_len != v2->objkey_len)
1074 return 0; /* no match because different length */
1076 /* Now do a byte comaprison */
1078 if (memcmp(v1->objkey,v2->objkey, v1->objkey_len) == 0) {
1079 return 1; /* compares ok */
1083 printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1086 return 0; /* found differences */
1089 /* Object Key Hash "HASH" Functions */
1091 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1092 const struct giop_object_key *key = (const struct giop_object_key *)v;
1095 guint32 val = 0; /* init hash value */
1099 * Hmm, try this simple hashing scheme for now.
1100 * ie: Simple summation
1106 printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1109 for (i=0; i< key->objkey_len; i++) {
1110 val += (guint8) key->objkey[i];
1118 * Routine to take an object key octet sequence, and length, and ptr to
1119 * a (null terminated )repository ID string, and store them in the obect key hash.
1121 * Blindly Inserts even if it does exist, See TODO at top for reason.
1124 static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
1126 struct giop_object_key objkey_key, *new_objkey_key;
1127 struct giop_object_val *objkey_val = NULL;
1129 objkey_key.objkey_len = len; /* length */
1130 objkey_key.objkey = obj; /* object key octet sequence */
1132 /* Look it up to see if it exists */
1134 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1136 /* CHANGED -- Same reqid, so abandon old entry */
1139 g_hash_table_remove(hash, &objkey_key);
1142 /* So, passed key should NOT exist in hash at this point.*/
1144 new_objkey_key = g_mem_chunk_alloc(giop_objkey_keys);
1145 new_objkey_key->objkey_len = len; /* save it */
1146 new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */
1148 objkey_val = g_mem_chunk_alloc(giop_objkey_vals);
1149 objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
1150 objkey_val->src = src; /* where IOR came from */
1154 printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
1155 objkey_val->repo_id, new_objkey_key->objkey_len);
1158 g_hash_table_insert(hash, new_objkey_key, objkey_val);
1165 * convert an ascii char representing a hex value,
1166 * to a numeric value.
1168 * returns value, or -1 if problem.
1172 static gint8 hex_char_to_val(guchar c){
1179 retval = c - 48; /* convert digit */
1183 c = toupper(c); /* convert to uppercase */
1184 if (c >= 'A' && c <= 'F') {
1195 * Convert from stringified IOR of the kind IOR:af4f7e459f....
1196 * to an IOR octet sequence.
1198 * User must free buffer.
1200 * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1201 * grab repoid etc for our objkey hash.
1205 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1208 gint8 tmpval; /* complete value */
1211 *out = g_new0(guint8, in_len); /* allocate buffer */
1217 /* skip past IOR: and convert character pairs to guint8 */
1219 for (i=4; i<in_len-1; i+=2) {
1220 if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1222 if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1223 g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1227 if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1228 g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1231 tmpval = tmpval_msb << 4;
1232 tmpval += tmpval_lsb;
1233 (*out)[(i-4)/2] = (guint8) tmpval;
1243 return (i-4)/2; /* length */
1250 * Simple getline, copied from somewhere :)
1254 static int getline(FILE *fp, gchar *line, int maxlen) {
1256 if (fgets(line,maxlen,fp) == NULL)
1259 return strlen(line);
1265 * Read a list of stringified IOR's from a named file, convert to IOR's
1266 * and store in object key hash
1269 static void read_IOR_strings_from_file(gchar *name, int max_iorlen) {
1270 guchar *buf; /* NOTE reused for every line */
1272 int ior_val_len; /* length after unstringifying. */
1274 guint8 *out; /* ptr to unstringified IOR */
1275 tvbuff_t *tvb; /* temp tvbuff for dissectin IORs */
1276 guint32 my_offset = 0;
1277 gboolean stream_is_big_endian;
1280 fp = fopen(name,"r"); /* open read only */
1283 if (errno == EACCES)
1284 fprintf(stderr, "Error opening file IOR.txt for reading: %s\n",strerror(errno));
1288 buf = g_malloc0(max_iorlen+1); /* input buf */
1290 while ((len = getline(fp,buf,max_iorlen+1)) > 0) {
1291 my_offset = 0; /* reset for every IOR read */
1293 ior_val_len = string_to_IOR(buf,len,&out); /* convert */
1297 /* Combination of tvb_new() and tvb_set_real_data().
1298 Can throw ReportedBoundsError.
1300 XXX - can it throw an exception in this case? If so, we
1301 need to catch it and clean up, but we really shouldn't allow
1302 it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
1305 tvb = tvb_new_real_data(out, ior_val_len, ior_val_len);
1307 stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1308 decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1318 fclose(fp); /* be nice */
1326 * Init routine, setup our request hash stuff, or delete old ref's
1328 * Cannot setup the module hash here as my init() may not be called before
1329 * users start registering. So I will move the module_hash stuff to
1330 * proto_register_giop, as is done with packet-rpc
1334 * Also, setup our objectkey/repoid hash here.
1338 static void giop_init(void) {
1342 * Create objkey/repoid hash, use my "equal" and "hash" functions.
1346 if (giop_objkey_hash)
1347 g_hash_table_destroy(giop_objkey_hash);
1348 if (giop_objkey_keys)
1349 g_mem_chunk_destroy(giop_objkey_keys);
1350 if (giop_objkey_vals)
1351 g_mem_chunk_destroy(giop_objkey_vals);
1355 * Create hash, use my "equal" and "hash" functions.
1359 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1361 giop_objkey_keys = g_mem_chunk_new("giop_objkey_keys",
1362 sizeof(struct giop_object_key),
1363 giop_objkey_init_count * sizeof(struct giop_object_key),
1366 giop_objkey_vals = g_mem_chunk_new("giop_objkey_vals",
1367 sizeof(struct giop_object_val),
1368 giop_objkey_init_count * sizeof(struct giop_object_val),
1373 * Create complete_reply_hash, use my "equal" and "hash" functions.
1377 if (giop_complete_reply_hash)
1378 g_hash_table_destroy(giop_complete_reply_hash);
1379 if (giop_complete_reply_keys)
1380 g_mem_chunk_destroy(giop_complete_reply_keys);
1381 if (giop_complete_reply_vals)
1382 g_mem_chunk_destroy(giop_complete_reply_vals);
1386 * Create hash, use my "equal" and "hash" functions.
1390 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1392 giop_complete_reply_keys = g_mem_chunk_new("giop_complete_reply_keys",
1393 sizeof(struct complete_reply_hash_key),
1394 complete_reply_hash_count * sizeof(struct complete_reply_hash_key),
1397 giop_complete_reply_vals = g_mem_chunk_new("giop_complete_reply_vals",
1398 sizeof(struct complete_reply_hash_val),
1399 complete_reply_hash_count * sizeof(struct complete_reply_hash_val),
1404 read_IOR_strings_from_file("IOR.txt", 600); /* testing */
1411 * Insert an entry in the GIOP Heuristic User table.
1413 * Uses giop_sub_handle_t to wrap giop user info.
1417 void register_giop_user(giop_sub_dissector_t *sub, gchar *name, int sub_proto) {
1419 giop_sub_handle_t *subh;
1421 subh = g_malloc(sizeof (giop_sub_handle_t));
1423 subh->sub_name = name;
1425 subh->sub_proto = sub_proto; /* proto_XXX from sub dissectors's proto_register_protocol() */
1427 giop_sub_list = g_slist_append (giop_sub_list, subh);
1433 * Lookup an object key in our object key hash, and return the corresponding
1438 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1440 struct giop_object_key objkey_key;
1441 struct giop_object_val *objkey_val = NULL;
1443 objkey_key.objkey_len = len; /* length */
1444 objkey_key.objkey = obj; /* object key octet sequence */
1446 /* Look it up to see if it exists */
1448 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1452 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1454 return objkey_val->repo_id; /* found */
1458 printf("FAILED Lookup of object key \n" );
1461 return NULL; /* not found */
1467 * Extract top level module/interface from repoid
1469 * eg from - "IDL:Echo/interface1:1.0"
1472 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1473 * get linux.org/Penguin/Teeth
1476 * User must free returned ptr after use.
1478 * TODO -- generalize for other Repoid encodings
1481 static gchar * get_modname_from_repoid(gchar *repoid) {
1483 gchar *modname = NULL;
1484 gchar *saved_repoid = NULL;
1486 guint8 stop_mod; /* Index of last character of modname in Repoid */
1487 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1490 saved_repoid = g_strdup(repoid); /* make a copy */
1492 /* Must start with IDL: , otherwise I get confused */
1494 if (g_strncasecmp("IDL:",repoid,4))
1497 /* Looks like a RepoID to me, so get Module or interface name */
1499 /* TODO -- put some code here to get Module name */
1501 for(i=4; c != '\0'; i++) {
1503 stop_mod = i; /* save */
1504 if (c == ':' ) /* delimiters */
1509 /* Now create a new string based on start and stop and \0 */
1511 modname = g_strndup(repoid+4, stop_mod - start_mod);
1526 * Display a "module" hash entry
1529 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1531 struct giop_module_val *mv = (struct giop_module_val *) val;
1532 struct giop_module_key *mk = (struct giop_module_key *) key;
1534 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1541 * Display a "complete_reply " hash entry
1544 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1546 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1547 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1549 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1557 * Display an "objkey" hash entry
1560 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1562 struct giop_object_val *mv = (struct giop_object_val *) val;
1563 struct giop_object_key *mk = (struct giop_object_key *) key;
1566 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1568 for (i=0; i<mk->objkey_len; i++) {
1569 printf("%.2x ", mk->objkey[i]);
1573 * If read from file, mark it as such..
1577 printf(", Repo ID = %s \n", mv->repo_id);
1580 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1588 * Display all giop_sub_list (GSList) entries
1591 static void display_heuristic_user_list() {
1594 giop_sub_handle_t *subh; /* handle */
1596 /* Get length of list */
1597 len = g_slist_length(giop_sub_list); /* find length */
1602 for (i=0; i<len; i++) {
1603 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1604 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1610 * Display all complete_request_list (GList) entries
1613 static void display_complete_request_list() {
1616 comp_req_list_entry_t *entry;
1618 /* Get length of list */
1619 len = g_list_length(giop_complete_request_list); /* find length */
1624 for (i=0; i<len; i++) {
1625 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1626 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1627 entry->reqid,entry->operation, entry->repoid);
1635 /* Dump Hash/List contents
1637 * collection_type specifies the list or hash to dump
1641 static void giop_dump_collection(collection_data_t collection_type) {
1643 switch(collection_type) {
1644 case cd_heuristic_users:
1645 printf("+----------------------------------------------+ \n");
1646 printf("+-------------- Heuristic User (Begin) --------+ \n");
1647 printf("+----------------------------------------------+ \n");
1649 display_heuristic_user_list();
1651 printf("+----------------------------------------------+ \n");
1652 printf("+-------------- Heuristic User (End) ----------+ \n");
1653 printf("+----------------------------------------------+ \n");
1657 case cd_complete_request_list:
1658 printf("+----------------------------------------------+ \n");
1659 printf("+------------- Complete Request List (Begin) --+ \n");
1660 printf("+----------------------------------------------+ \n");
1662 display_complete_request_list();
1664 printf("+----------------------------------------------+ \n");
1665 printf("+------------ Complete Request List (End) -----+ \n");
1666 printf("+----------------------------------------------+ \n");
1670 case cd_module_hash:
1671 printf("+----------------------------------------------+ \n");
1672 printf("+-------------- Module (Begin) ----------------+ \n");
1673 printf("+----------------------------------------------+ \n");
1675 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1677 printf("+----------------------------------------------+ \n");
1678 printf("+-------------- Module ( End) -----------------+ \n");
1679 printf("+----------------------------------------------+ \n\n");
1683 case cd_objkey_hash:
1684 printf("+----------------------------------------------+ \n");
1685 printf("+-------------- Objkey (Begin) ----------------+ \n");
1686 printf("+----------------------------------------------+ \n");
1688 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1690 printf("+----------------------------------------------+ \n");
1691 printf("+-------------- Objkey (End) ------------------+ \n");
1692 printf("+----------------------------------------------+ \n\n");
1696 case cd_complete_reply_hash:
1697 printf("+----------------------------------------------+ \n");
1698 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1699 printf("+----------------------------------------------+ \n");
1701 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1703 printf("+----------------------------------------------+ \n");
1704 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1705 printf("+----------------------------------------------+ \n");
1711 printf("giop: giop_dump_collection: Unknown type \n");
1722 * Loop through all subdissectors, and call them until someone
1723 * answers (returns TRUE). This function then returns TRUE, otherwise
1726 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1729 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1730 MessageHeader *header, gchar *operation ) {
1733 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1734 giop_sub_handle_t *subh = NULL;
1735 const char *saved_proto;
1737 len = g_slist_length(giop_sub_list); /* find length */
1742 saved_proto = pinfo->current_proto;
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 pinfo->current_proto =
1748 proto_get_protocol_short_name(subh->sub_proto);
1749 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1751 pinfo->current_proto = saved_proto;
1752 return TRUE; /* found one, lets return */
1754 } /* protocol_is_enabled */
1757 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1758 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
1760 pinfo->current_proto = saved_proto;
1761 return res; /* result */
1767 * Find the matching repoid in the module hash and call
1768 * the dissector function if offset exists.
1771 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1772 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1778 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1779 MessageHeader *header, gchar *operation, gchar *repoid ) {
1781 giop_sub_handle_t *subdiss = NULL; /* handle */
1782 gboolean res = FALSE;
1783 gchar *modname = NULL;
1784 struct giop_module_key module_key;
1785 struct giop_module_val *module_val = NULL;
1786 const char *saved_proto;
1790 * Get top level module/interface from complete repoid
1793 modname = get_modname_from_repoid(repoid);
1794 if (modname == NULL) {
1795 return res; /* unknown module name */
1799 /* Search for Module or interface name */
1801 module_key.module = modname; /* module name */
1802 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1804 if (module_val == NULL) {
1805 return res; /* module not registered */
1808 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1811 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1812 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1813 /* but only if user not clicking */
1815 if (!pinfo->fd->flags.visited)
1816 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1819 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1821 if (tvb_offset_exists(tvb, *offset)) {
1823 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1826 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1828 saved_proto = pinfo->current_proto;
1829 pinfo->current_proto =
1830 proto_get_protocol_short_name(subdiss->sub_proto);
1831 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1832 pinfo->current_proto = saved_proto;
1834 } /* protocol_is_enabled */
1835 } /* offset exists */
1838 return res; /* return result */
1843 /* Take in an array of char and create a new string.
1844 * Replace non-printable characters with periods.
1846 * The array may contain \0's so dont use strdup
1847 * The string is \0 terminated, and thus longer than
1848 * the initial sequence.
1849 * Caller must free the new string.
1852 static gchar * make_printable_string (gchar *in, guint32 len) {
1854 gchar *print_string = NULL;
1856 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1857 memcpy(print_string, in, len); /* and make a copy of input data */
1859 for(i=0; i < len; i++) {
1860 if( !isprint( (unsigned char)print_string[i] ) )
1861 print_string[i] = '.';
1864 return print_string; /* return ptr */
1867 /* Determine the byte order from the GIOP MessageHeader */
1869 gboolean is_big_endian (MessageHeader * header) {
1870 gboolean big_endian = FALSE;
1872 switch (header->GIOP_version.minor) {
1875 if (header->flags & 0x01)
1895 * Calculate new offset, based on the current offset, and user supplied
1896 * "offset delta" value, and the alignment requirement.
1900 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1901 * aligned on 8 byte boundaries.
1904 static void set_new_alignment(int *offset, int delta, int alignment) {
1906 while( ( (*offset + delta) % alignment) != 0)
1915 * ------------------------------------------------------------------------------------------+
1916 * Public get_CDR_xxx functions.
1917 * ------------------------------------------------------------------------------------------+
1923 * Gets data of type any. This is encoded as a TypeCode
1924 * followed by the encoded value.
1927 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1928 gboolean stream_is_big_endian, int boundary,
1929 MessageHeader * header ) {
1931 guint32 TCKind; /* TypeCode */
1933 /* get TypeCode of any */
1934 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1936 /* dissect data of type TCKind */
1937 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1941 /* Copy a 1 octet sequence from the tvbuff
1942 * which represents a boolean value, and convert
1943 * it to a boolean value.
1944 * Offset is then incremented by 1, to indicate the 1 octet which
1945 * has been processed.
1948 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1951 val = tvb_get_guint8(tvb, *offset); /* easy */
1956 /* Copy a 1 octet sequence from the tvbuff
1957 * which represents a char, and convert
1958 * it to an char value.
1959 * offset is then incremented by 1, to indicate the 1 octet which
1960 * has been processed.
1963 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1966 val = tvb_get_guint8(tvb, *offset); /* easy */
1974 * Floating Point Data Type double IEEE 754-1985
1976 * Copy an 8 octet sequence from the tvbuff
1977 * which represents a double value, and convert
1978 * it to a double value, taking into account byte order.
1979 * offset is first incremented so that it falls on a proper alignment
1980 * boundary for double values.
1981 * offset is then incremented by 8, to indicate the 8 octets which
1982 * have been processed.
1985 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1989 /* double values must be aligned on a 8 byte boundary */
1991 while( ( (*offset + boundary) % 8) != 0)
1994 val = (stream_is_big_endian) ? tvb_get_ntohieee_double (tvb, *offset) :
1995 tvb_get_letohieee_double (tvb, *offset);
2003 /* Copy a 4 octet sequence from the tvbuff
2004 * which represents an enum value, and convert
2005 * it to an enum value, taking into account byte order.
2006 * offset is first incremented so that it falls on a proper alignment
2007 * boundary for an enum (4)
2008 * offset is then incremented by 4, to indicate the 4 octets which
2009 * have been processed.
2011 * Enum values are encoded as unsigned long.
2015 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2017 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2023 * Copy an octet sequence from the tvbuff
2024 * which represents a Fixed point decimal type, and create a string representing
2025 * a Fixed point decimal type. There are no alignment restrictions.
2026 * Size and scale of fixed decimal type is determined by IDL.
2028 * digits - IDL specified number of "digits" for this fixed type
2029 * scale - IDL specified "scale" for this fixed type
2032 * eg: typedef fixed <5,2> fixed_t;
2033 * could represent numbers like 123.45, 789.12,
2036 * As the fixed type could be any size, I will not try to fit it into our
2037 * simple types like gdouble or glong etc. I will just create a string buffer holding
2038 * a representation (after scale is applied), and with a decimal point or zero padding
2039 * inserted at the right place if necessary. The string is null terminated
2041 * so string may look like
2044 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2046 * According to spec, digits <= 31
2047 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2050 * User must remember to free the buffer
2055 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2057 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2058 guint32 i ; /* loop */
2059 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2060 /* this does not include sign, decimal point and \0 */
2061 guint32 sindex = 0; /* string index */
2062 gchar *tmpbuf; /* temp buff, holds string without scaling */
2063 guint8 tval; /* temp val storage */
2066 * how many bytes to hold digits and scale (if scale <0)
2068 * eg: fixed <5,2> = 5 digits
2069 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2073 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2077 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2079 slen = digits; /* digits */
2083 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2086 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2089 * Register a cleanup function in case on of our tvbuff accesses
2090 * throws an exception. We need to clean up tmpbuf.
2092 CLEANUP_PUSH(g_free, tmpbuf);
2094 /* If even , grab 1st dig */
2096 if (!(digits & 0x01)) {
2097 tval = get_CDR_octet(tvb,offset);
2099 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2101 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2106 * Loop, but stop BEFORE we hit last digit and sign
2107 * if digits = 1 or 2, then this part is skipped
2111 for(i=0; i< ((digits-1)/2 ); i++) {
2112 tval = get_CDR_octet(tvb,offset);
2114 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2117 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2119 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2126 printf("giop:get_CDR_fixed(): before last digit \n");
2130 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2132 tval = get_CDR_octet(tvb,offset);
2134 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2136 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2139 sign = tval & 0x0f; /* get sign */
2141 /* So now, we have all digits in an array, and the sign byte
2142 * so lets generate a printable string, taking into account the scale
2146 sindex = 0; /* reset */
2147 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2148 * \0 -- TODO check slen is reasonable first */
2150 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2155 (*seq)[sindex] = '+'; /* put sign in first string position */
2158 (*seq)[sindex] = '-';
2161 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2162 (*seq)[sindex] = '*'; /* flag as sign unkown */
2168 /* Add decimal point or padding 0's, depending if scale is positive or
2169 * negative, respectively
2173 for (i=0; i<digits-scale; i++) {
2174 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2178 (*seq)[sindex] = '.'; /* decimal point */
2181 for (i=digits-scale; i<digits; i++) {
2182 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2186 (*seq)[sindex] = '\0'; /* string terminator */
2190 /* negative scale, dump digits and pad out with 0's */
2192 for (i=0; i<digits-scale; i++) {
2194 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2196 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2201 (*seq)[sindex] = '\0'; /* string terminator */
2206 * We're done with tmpbuf, so we can call the cleanup handler to free
2207 * it, and then pop the cleanup handler.
2209 CLEANUP_CALL_AND_POP;
2212 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2222 * Floating Point Data Type float IEEE 754-1985
2224 * Copy an 4 octet sequence from the tvbuff
2225 * which represents a float value, and convert
2226 * it to a float value, taking into account byte order.
2227 * offset is first incremented so that it falls on a proper alignment
2228 * boundary for float values.
2229 * offset is then incremented by 4, to indicate the 4 octets which
2230 * have been processed.
2233 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2237 /* float values must be aligned on a 4 byte boundary */
2239 while( ( (*offset + boundary) % 4) != 0)
2242 val = (stream_is_big_endian) ? tvb_get_ntohieee_float (tvb, *offset) :
2243 tvb_get_letohieee_float (tvb, *offset);
2252 * Decode an Interface type, and display it on the tree.
2255 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2256 gboolean stream_is_big_endian, int boundary) {
2259 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2265 /* Copy a 4 octet sequence from the tvbuff
2266 * which represents a signed long value, and convert
2267 * it to an signed long vaule, taking into account byte order.
2268 * offset is first incremented so that it falls on a proper alignment
2269 * boundary for long values.
2270 * offset is then incremented by 4, to indicate the 4 octets which
2271 * have been processed.
2274 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2278 /* unsigned long values must be aligned on a 4 byte boundary */
2279 while( ( (*offset + boundary) % 4) != 0)
2282 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2283 tvb_get_letohl (tvb, *offset);
2290 * Decode an Object type, and display it on the tree.
2293 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2294 gboolean stream_is_big_endian, int boundary) {
2296 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2302 /* Copy a 1 octet sequence from the tvbuff
2303 * which represents a octet, and convert
2304 * it to an octet value.
2305 * offset is then incremented by 1, to indicate the 1 octet which
2306 * has been processed.
2309 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2312 val = tvb_get_guint8(tvb, *offset); /* easy */
2318 /* Copy a sequence of octets from the tvbuff.
2319 * Caller of this function must remember to free the
2320 * array pointed to by seq.
2321 * This function also increments offset by len.
2324 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, guint32 len) {
2327 * Make sure that the entire sequence of octets is in the buffer before
2328 * allocating the buffer, so that we don't have to worry about freeing
2329 * the buffer, and so that we don't try to allocate a buffer bigger
2330 * than the data we'll actually be copying, and thus don't run the risk
2331 * of crashing if the buffer is *so* big that we fail to allocate it
2332 * and "g_new0()" aborts.
2334 tvb_ensure_bytes_exist(tvb, *offset, len);
2337 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2338 * do what we do now, and null-terminate the string (which also means
2339 * we don't need to zero out the entire allocation, just the last byte)?
2341 *seq = g_new0(gchar, len + 1);
2342 tvb_memcpy( tvb, *seq, *offset, len);
2347 /* Copy a 2 octet sequence from the tvbuff
2348 * which represents a signed short value, and convert
2349 * it to a signed short value, taking into account byte order.
2350 * offset is first incremented so that it falls on a proper alignment
2351 * boundary for short values.
2352 * offset is then incremented by 2, to indicate the 2 octets which
2353 * have been processed.
2356 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2360 /* short values must be aligned on a 2 byte boundary */
2361 while( ( (*offset + boundary) % 2) != 0)
2364 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2365 tvb_get_letohs (tvb, *offset);
2373 /* Copy an octet sequence from the tvbuff
2374 * which represents a string, and convert
2375 * it to an string value, taking into account byte order.
2376 * offset is first incremented so that it falls on a proper alignment
2377 * boundary for string values. (begins with an unsigned long LI)
2379 * String sequence is copied to a buffer "seq". This must
2380 * be freed by the calling program.
2381 * offset is then incremented, to indicate the octets which
2382 * have been processed.
2384 * returns number of octets in the sequence
2386 * Note: This function only supports single byte encoding at the
2387 * moment until I get a handle on multibyte encoding etc.
2392 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2397 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2400 (*offset)++; /* must step past \0 delimiter */
2404 get_CDR_octet_seq(tvb, seq, offset, slength);
2406 *seq = g_strdup(""); /* zero-length string */
2409 return slength; /* return length */
2413 /* Process a sequence of octets that represent the
2414 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2416 * This function also increments offset to the correct position.
2418 * It will parse the TypeCode and output data to the "tree" provided
2421 * It returns a guint32 representing a TCKind value.
2424 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2425 gboolean stream_is_big_endian, int boundary,
2426 MessageHeader * header ) {
2429 gint16 s_octet2; /* signed int16 */
2430 guint16 u_octet2; /* unsigned int16 */
2431 guint32 u_octet4; /* unsigned int32 */
2433 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2435 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2436 *offset-sizeof(val),4,val);
2439 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2442 case tk_null: /* empty parameter list */
2444 case tk_void: /* empty parameter list */
2446 case tk_short: /* empty parameter list */
2448 case tk_long: /* empty parameter list */
2450 case tk_ushort: /* empty parameter list */
2452 case tk_ulong: /* empty parameter list */
2454 case tk_float: /* empty parameter list */
2456 case tk_double: /* empty parameter list */
2458 case tk_boolean: /* empty parameter list */
2460 case tk_char: /* empty parameter list */
2462 case tk_octet: /* empty parameter list */
2464 case tk_any: /* empty parameter list */
2466 case tk_TypeCode: /* empty parameter list */
2468 case tk_Principal: /* empty parameter list */
2470 case tk_objref: /* complex parameter list */
2471 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary);
2473 case tk_struct: /* complex parameter list */
2474 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2476 case tk_union: /* complex parameter list */
2477 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2479 case tk_enum: /* complex parameter list */
2480 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary);
2483 case tk_string: /* simple parameter list */
2484 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2486 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2487 *offset-sizeof(u_octet4),4,u_octet4);
2491 case tk_sequence: /* complex parameter list */
2492 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2494 case tk_array: /* complex parameter list */
2495 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2497 case tk_alias: /* complex parameter list */
2498 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2500 case tk_except: /* complex parameter list */
2501 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2503 case tk_longlong: /* empty parameter list */
2505 case tk_ulonglong: /* empty parameter list */
2507 case tk_longdouble: /* empty parameter list */
2509 case tk_wchar: /* empty parameter list */
2511 case tk_wstring: /* simple parameter list */
2512 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2514 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2515 *offset-sizeof(u_octet4),4,u_octet4);
2519 case tk_fixed: /* simple parameter list */
2520 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2522 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2523 *offset-sizeof(u_octet2),2,u_octet2);
2526 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2528 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2529 *offset-sizeof(s_octet2),2,s_octet2);
2533 case tk_value: /* complex parameter list */
2534 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2536 case tk_value_box: /* complex parameter list */
2537 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2539 case tk_native: /* complex parameter list */
2540 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary);
2542 case tk_abstract_interface: /* complex parameter list */
2543 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary );
2546 g_warning("giop: Unknown TCKind %u \n", val);
2555 /* Copy a 4 octet sequence from the tvbuff
2556 * which represents an unsigned long value, and convert
2557 * it to an unsigned long vaule, taking into account byte order.
2558 * offset is first incremented so that it falls on a proper alignment
2559 * boundary for unsigned long values.
2560 * offset is then incremented by 4, to indicate the 4 octets which
2561 * have been processed.
2564 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2568 /* unsigned long values must be aligned on a 4 byte boundary */
2569 while( ( (*offset + boundary) % 4) != 0)
2572 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2573 tvb_get_letohl (tvb, *offset);
2580 /* Copy a 2 octet sequence from the tvbuff
2581 * which represents an unsigned short value, and convert
2582 * it to an unsigned short value, taking into account byte order.
2583 * offset is first incremented so that it falls on a proper alignment
2584 * boundary for unsigned short values.
2585 * offset is then incremented by 2, to indicate the 2 octets which
2586 * have been processed.
2589 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2593 /* unsigned short values must be aligned on a 2 byte boundary */
2594 while( ( (*offset + boundary) % 2) != 0)
2597 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2598 tvb_get_letohs (tvb, *offset);
2606 /* Copy a wchar from the tvbuff.
2607 * Caller of this function must remember to free the
2608 * array pointed to by seq.
2609 * This function also increments offset according to
2612 * For GIOP 1.1 read 2 octets and return size -2. The
2613 * negation means there is no size element in the packet
2614 * and therefore no size to add to the tree.
2616 * For GIOP 1.2 read size of wchar and the size
2617 * octets. size is returned as a gint8.
2619 * For both GIOP versions the wchar is returned
2620 * as a printable string.
2624 /* NOTE: This is very primitive in that it just reads
2625 * the wchar as a series of octets and returns them
2626 * to the user. No translation is attempted based on
2627 * byte orientation, nor on code set. I.e it only
2628 * really reads past the wchar and sets the offset
2632 /* The "decoding" is done according to CORBA chapter 15.
2633 * Wchar is not supported for GIOP 1.0.
2636 gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2641 /* CORBA chapter 15:
2642 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2643 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2644 * followed by the elements of the octet sequence representing
2645 * the encoded value of the wchar.
2648 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2649 slength = 2; /* set for GIOP 1.1 length in octets */
2651 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2652 slength = get_CDR_octet(tvb,offset);
2655 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2656 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2658 /* now turn octets (wchar) into something that can be printed by the user */
2659 *seq = make_printable_string(raw_wstring, slength);
2661 g_free(raw_wstring);
2664 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2665 if (header->GIOP_version.minor < 2)
2668 return slength; /* return length */
2673 /* Copy a wstring from the tvbuff.
2674 * Caller of this function must remember to free the
2675 * array pointed to by seq.
2676 * This function also increments offset, according to
2677 * wstring length. length is returned as guint32
2680 /* NOTE: This is very primitive in that it just reads
2681 * the wstring as a series of octets and returns them
2682 * to the user. No translation is attempted based on
2683 * byte orientation, nor on code set. I.e it only
2684 * really reads past the wstring and sets the offset
2688 /* The "decoding" is done according to CORBA chapter 15.
2689 * Wstring is not supported for GIOP 1.0.
2693 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2694 int boundary, MessageHeader * header) {
2699 /* CORBA chapter 15:
2700 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2701 * length and string are NUL terminated (length???).
2702 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2706 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2708 /* get length, same for all GIOP versions,
2709 * although for 1.2 CORBA doesnt say, so assume.
2711 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2715 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2716 slength = 5; /* better than core dumping during debug */
2720 if (header->GIOP_version.minor < 2) {
2722 (*offset)++; /* must step past \0 delimiter */
2724 /* assume length is number of characters and not octets, spec not clear */
2725 slength = slength * 2; /* length in octets is 2 * wstring length */
2729 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2731 /* now turn octets (wstring) into something that can be printed by the user */
2732 *seq = make_printable_string(raw_wstring, slength);
2734 g_free(raw_wstring);
2737 return slength; /* return length */
2744 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2746 * typedef short AddressingDisposition;
2747 * const short KeyAddr = 0;
2748 * const short ProfileAddr = 1;
2749 * const short ReferenceAddr = 2;
2750 * struct IORAddressingInfo {
2751 * unsigned long selected_profile_index;
2755 * union TargetAddress switch (AddressingDisposition) {
2756 * case KeyAddr: sequence <octet> object_key;
2757 * case ProfileAddr: IOP::TaggedProfile profile;
2758 * case ReferenceAddr: IORAddressingInfo ior;
2763 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2764 gboolean stream_is_big_endian)
2766 guint16 discriminant;
2768 gchar *p_object_key;
2772 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2775 proto_tree_add_text (tree, tvb, *offset -2, 2,
2776 "TargetAddress Discriminant: %u", discriminant);
2779 switch (discriminant)
2781 case 0: /* KeyAddr */
2782 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2785 proto_tree_add_text (tree, tvb, *offset -4, 4,
2786 "KeyAddr (object key length): %u", len);
2791 get_CDR_octet_seq(tvb, &object_key, offset, len);
2792 p_object_key = make_printable_string( object_key, len );
2796 proto_tree_add_text (tree, tvb, *offset -len, len,
2797 "KeyAddr (object key): %s", p_object_key);
2799 g_free( p_object_key );
2800 g_free( object_key );
2803 case 1: /* ProfileAddr */
2804 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2805 stream_is_big_endian, NULL);
2807 case 2: /* ReferenceAddr */
2808 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2812 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2813 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2816 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2824 dissect_reply_body (tvbuff_t *tvb, guint offset, packet_info *pinfo,
2825 proto_tree *tree, gboolean stream_is_big_endian,
2826 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2828 guint sequence_length;
2829 gboolean exres = FALSE; /* result of trying explicit dissectors */
2830 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2833 * comp_req_list stuff
2836 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2840 switch (reply_status)
2842 case SYSTEM_EXCEPTION:
2844 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2847 case USER_EXCEPTION:
2849 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2853 proto_tree_add_text(tree, tvb, offset-4, 4,
2854 "Exception length: %u", sequence_length);
2856 if (sequence_length != 0)
2860 proto_tree_add_text(tree, tvb, offset, sequence_length,
2862 tvb_format_text(tvb, offset, sequence_length));
2866 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2868 /* read exception id from buffer and store in*/
2870 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2876 offset += sequence_length;
2882 * Now just fall through to the NO_EXCEPTION part
2883 * as this is common .
2891 /* lookup MFN in hash directly */
2893 mfn = get_mfn_from_fn(pinfo->fd->num);
2895 if (mfn == pinfo->fd->num)
2896 return; /* no matching frame number, what am I */
2898 /* get entry for this MFN */
2899 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2902 return; /* no matching entry */
2906 * If this packet is a REPLY to a RESOLVE(request)
2908 * TODO - make this lookup faster -- FS
2911 if (!strcmp(giop_op_resolve,entry->operation)) {
2912 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2916 /* TODO -- Put stuff here for other "interesting operations" */
2920 * Call sub dissector.
2921 * First try an find a explicit sub_dissector, then if that
2922 * fails, try the heuristic method.
2927 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
2930 /* Only call heuristic if no explicit dixxector was found */
2933 try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
2939 case LOCATION_FORWARD:
2940 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2944 case LOCATION_FORWARD_PERM:
2945 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2949 case NEEDS_ADDRESSING_MODE: {
2951 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2953 proto_tree_add_text (tree, tvb, offset -2, 2,
2954 "AddressingDisposition: %u", addr_disp);
2962 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
2968 g_free(repoid); /* free resource */
2978 /* The format of the Reply Header for GIOP 1.0 and 1.1
2979 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
2981 struct ReplyHeader_1_0 {
2982 IOP::ServiceContextList service_context;
2983 unsigned long request_id;
2984 ReplyStatusType_1_0 reply_status;
2988 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
2989 MessageHeader * header,
2990 gboolean stream_is_big_endian) {
2994 guint32 reply_status;
2995 proto_tree *reply_tree = NULL;
2997 guint32 mfn; /* matching frame number */
3000 tf = proto_tree_add_text (tree, tvb, offset, -1,
3001 "General Inter-ORB Protocol Reply");
3002 if (reply_tree == NULL)
3004 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3010 * Decode IOP::ServiceContextList
3013 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3015 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3017 if (check_col(pinfo->cinfo, COL_INFO)) {
3018 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3022 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3023 "Request id: %u", request_id);
3026 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3028 if (check_col(pinfo->cinfo, COL_INFO)) {
3029 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3030 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3035 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3037 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3042 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3045 if (! pinfo->fd->flags.visited) {
3046 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3047 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3048 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3052 header->req_id = request_id; /* save for sub dissector */
3053 header->rep_status = reply_status; /* save for sub dissector */
3055 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3056 reply_status, header,tree);
3061 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3062 * and 1.1 header, only the fields have been rearranged. From Section
3063 * 15.4.3.1 of the CORBA 2.4 specification:
3065 * struct ReplyHeader_1_2 {
3066 * unsigned long request_id;
3067 * ReplyStatusType_1_2 reply_status;
3068 * IOP:ServiceContextList service_context;
3072 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3074 MessageHeader * header,
3075 gboolean stream_is_big_endian) {
3079 guint32 reply_status;
3080 proto_tree *reply_tree = NULL;
3082 guint32 mfn; /* matching frame number */
3085 tf = proto_tree_add_text (tree, tvb, offset, -1,
3086 "General Inter-ORB Protocol Reply");
3087 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3090 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3092 if (check_col(pinfo->cinfo, COL_INFO)) {
3093 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3097 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3098 "Request id: %u", request_id);
3101 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3103 if (check_col(pinfo->cinfo, COL_INFO)) {
3104 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3105 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3110 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3112 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3117 * Decode IOP::ServiceContextList
3120 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3123 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3126 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3129 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3132 if (! pinfo->fd->flags.visited) {
3133 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3134 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3135 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3140 * Add header to argument list so sub dissector can get header info.
3143 header->req_id = request_id; /* save for sub dissector */
3144 header->rep_status = reply_status; /* save for sub dissector */
3146 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3147 reply_status,header,tree);
3153 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3155 gboolean stream_is_big_endian) {
3159 proto_tree *cancel_request_tree = NULL;
3163 tf = proto_tree_add_text (tree, tvb, offset, -1,
3164 "General Inter-ORB Protocol CancelRequest");
3165 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3168 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3170 if (check_col(pinfo->cinfo, COL_INFO)) {
3171 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3175 proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4,
3176 "Request id: %u", request_id);
3182 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3183 * in section 15.4.2.1 of the CORBA 2.4 specification.
3185 * struct RequestHeader{
3186 * IOP::ServiceContextList service_context;
3187 * unsigned long request_id;
3188 * boolean response_expected;
3189 * octet reserved[3]; // Only in GIOP 1.1
3190 * sequence<octet> object_key;
3192 * CORBA::OctetSeq requesting_principal;
3196 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3198 MessageHeader * header, gboolean stream_is_big_endian)
3204 guint32 objkey_len = 0; /* object key length */
3205 gchar *objkey = NULL; /* object key sequence */
3206 gchar *print_objkey; /* printable object key sequence */
3207 gboolean exres = FALSE; /* result of trying explicit dissectors */
3210 gchar *requesting_principal;
3211 gchar *print_requesting_principal;
3212 guint8 response_expected;
3214 proto_tree *request_tree = NULL;
3217 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3222 tf = proto_tree_add_text (tree, tvb, offset, -1,
3223 "General Inter-ORB Protocol Request");
3224 if (request_tree == NULL)
3226 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3235 * Decode IOP::ServiceContextList
3238 decode_ServiceContextList(tvb, request_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3241 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3242 if (check_col(pinfo->cinfo, COL_INFO))
3244 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3248 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3249 "Request id: %u", request_id);
3252 response_expected = tvb_get_guint8( tvb, offset );
3254 if (check_col(pinfo->cinfo, COL_INFO))
3256 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3257 response_expected ? "two-way" : "one-way");
3261 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3262 "Response expected: %u", response_expected);
3265 if( header->GIOP_version.minor > 0)
3267 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3270 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3271 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3278 /* Length of object_key sequence */
3279 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3284 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3285 /**/ "Object Key length: %u", objkey_len);
3290 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3292 print_objkey = make_printable_string(objkey, objkey_len);
3296 proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
3297 /**/ "Object Key: %s", print_objkey);
3301 g_free( print_objkey );
3305 * Register a cleanup function in case on of our tvbuff accesses
3306 * throws an exception. We need to clean up objkey.
3308 CLEANUP_PUSH(g_free, objkey);
3310 /* length of operation string and string */
3311 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3314 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3315 /**/ "Operation length: %u", len);
3320 if (check_col(pinfo->cinfo, COL_INFO))
3322 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3326 proto_tree_add_text (request_tree, tvb, offset - len, len,
3327 /**/ "Operation: %s", operation);
3333 * Register a cleanup function in case on of our tvbuff accesses
3334 * throws an exception. We need to clean up operation.
3336 CLEANUP_PUSH(g_free, operation);
3338 /* length of requesting_principal string */
3339 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3342 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3343 /**/ "Requesting Principal Length: %u", len);
3348 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3350 print_requesting_principal = make_printable_string(requesting_principal, len);
3354 proto_tree_add_text (request_tree, tvb, offset - len, len,
3355 /**/ "Requesting Principal: %s", print_requesting_principal);
3359 g_free( print_requesting_principal );
3360 g_free( requesting_principal );
3365 * Save FN,reqid,and operation for later. Add sub_handle later.
3366 * But only if user is NOT clicking.
3369 if (! pinfo->fd->flags.visited)
3370 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3371 request_id,operation,NULL);
3375 * Call subdissector here before freeing "operation" and "key"
3376 * pass request_id also.
3377 * First try an find an explicit sub_dissector, then if that
3378 * fails, try the heuristic method.
3383 header->req_id = request_id; /* save for sub dissector */
3384 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3388 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3391 /* Only call heuristic if no explicit dissector was found */
3394 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3399 * We're done with operation, so we can call the cleanup handler to free
3400 * it, and then pop the cleanup handler.
3402 CLEANUP_CALL_AND_POP;
3405 * We're done with objkey, so we can call the cleanup handler to free
3406 * it, and then pop the cleanup handler.
3408 CLEANUP_CALL_AND_POP;
3412 /** The format of a GIOP 1.2 RequestHeader message is
3413 * (CORBA 2.4, sec. 15.4.2):
3415 * struct RequestHeader_1_2 {
3416 * unsigned long request_id;
3417 * octet response_flags;
3418 * octet reserved[3];
3419 * TargetAddress target;
3421 * IOP::ServiceContextList service_context;
3422 * // requesting_principal not in GIOP 1.2
3426 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3428 MessageHeader * header, gboolean stream_is_big_endian)
3433 guint8 response_flags;
3435 gchar *operation = NULL;
3436 proto_tree *request_tree = NULL;
3438 gboolean exres = FALSE; /* result of trying explicit dissectors */
3440 gchar *repoid = NULL;
3445 tf = proto_tree_add_text (tree, tvb, offset, -1,
3446 "General Inter-ORB Protocol Request");
3447 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3450 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3451 if (check_col(pinfo->cinfo, COL_INFO))
3453 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3457 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3458 "Request id: %u", request_id);
3461 response_flags = tvb_get_guint8( tvb, offset );
3465 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3466 "Response flags: %s (%u)",
3467 match_strval(response_flags, sync_scope),
3471 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3474 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3475 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3479 dissect_target_address(tvb, pinfo, &offset, request_tree, stream_is_big_endian);
3481 /* length of operation string */
3482 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3485 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3486 /**/ "Operation length: %u", len);
3491 if (check_col(pinfo->cinfo, COL_INFO))
3493 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3497 proto_tree_add_text (request_tree, tvb, offset - len, len,
3498 /**/ "Operation: %s", operation);
3505 * Register a cleanup function in case on of our tvbuff accesses
3506 * throws an exception. We need to clean up operation.
3508 CLEANUP_PUSH(g_free, operation);
3511 * Decode IOP::ServiceContextList
3514 decode_ServiceContextList(tvb, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3517 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3518 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3519 * GIOP octet stream start.
3522 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3525 * Save FN,reqid,and operation for later. Add sub_handle later.
3526 * But only if user is NOT clicking.
3529 if (! pinfo->fd->flags.visited)
3530 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3531 request_id,operation,NULL);
3535 * Call sub dissector.
3536 * First try an find a explicit sub_dissector, then if that
3537 * fails, try the heuristic method.
3542 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3545 /* Only call heuristic if no explicit dissector was found */
3548 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3553 * We're done with operation, so we can call the cleanup handler to free
3554 * it, and then pop the cleanup handler.
3556 CLEANUP_CALL_AND_POP;
3560 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3561 proto_tree * tree, MessageHeader * header,
3562 gboolean stream_is_big_endian)
3568 gchar *p_object_key;
3569 proto_tree *locate_request_tree = NULL;
3574 tf = proto_tree_add_text (tree, tvb, offset, -1,
3575 "General Inter-ORB Locate Request");
3576 if (locate_request_tree == NULL)
3578 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3583 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3584 if (check_col(pinfo->cinfo, COL_INFO))
3586 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3588 if (locate_request_tree)
3590 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3591 "Request id: %u", request_id);
3594 if(header->GIOP_version.minor < 2)
3596 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3597 if (locate_request_tree)
3599 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3600 "Object Key length: %u", len);
3604 get_CDR_octet_seq(tvb, &object_key, &offset, len);
3606 p_object_key = make_printable_string(object_key, len);
3608 if(locate_request_tree)
3611 proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
3612 "Object Key: %s", p_object_key);
3615 g_free(p_object_key);
3619 else /* GIOP 1.2 and higher */
3621 dissect_target_address(tvb, pinfo, &offset, locate_request_tree,
3622 stream_is_big_endian);
3628 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3629 proto_tree * tree, MessageHeader * header,
3630 gboolean stream_is_big_endian)
3634 guint32 locate_status;
3637 proto_tree *locate_reply_tree = NULL;
3642 tf = proto_tree_add_text (tree, tvb, offset, -1,
3643 "General Inter-ORB Locate Reply");
3644 if (locate_reply_tree == NULL)
3646 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3651 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3652 if (check_col(pinfo->cinfo, COL_INFO))
3654 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3656 if (locate_reply_tree)
3658 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3659 "Request id: %u", request_id);
3662 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3663 if (locate_reply_tree)
3665 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3666 "Locate status: %s",
3667 match_strval(locate_status, giop_locate_status_types)
3671 /* Decode the LocateReply body.
3673 * For GIOP 1.0 and 1.1 body immediately follows header.
3674 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3678 if (header->GIOP_version.minor > 1) {
3679 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3683 switch(locate_status) {
3684 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3685 case OBJECT_FORWARD_PERM:
3686 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3688 case LOC_SYSTEM_EXCEPTION:
3689 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3691 case LOC_NEEDS_ADDRESSING_MODE:
3692 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3693 if(locate_reply_tree) {
3694 proto_tree_add_text (tree, tvb, offset -2, 2,
3695 "AddressingDisposition: %u", addr_disp);
3698 default: /* others have no reply body */
3705 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3706 gboolean stream_is_big_endian)
3710 proto_tree *fragment_tree = NULL;
3715 tf = proto_tree_add_text (tree, tvb, offset, -1,
3716 "General Inter-ORB Fragment");
3717 if (fragment_tree == NULL)
3719 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3724 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3725 if (check_col(pinfo->cinfo, COL_INFO))
3727 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3731 proto_tree_add_text (fragment_tree, tvb, offset-4, 4,
3732 "Request id: %u", request_id);
3738 /* Main entry point */
3740 gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3742 MessageHeader header;
3743 tvbuff_t *giop_header_tvb;
3744 tvbuff_t *payload_tvb;
3746 proto_tree *clnp_tree = NULL;
3749 guint minor_version;
3750 gboolean stream_is_big_endian;
3756 giop_dump_collection(cd_module_hash);
3757 giop_dump_collection(cd_objkey_hash);
3758 giop_dump_collection(cd_heuristic_users);
3759 giop_dump_collection(cd_complete_reply_hash);
3760 giop_dump_collection(cd_complete_request_list);
3763 header.exception_id = NULL;
3765 /* check magic number and version */
3768 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
3770 if (tvb_length_remaining(tvb, 0) < GIOP_HEADER_SIZE)
3772 /* Not enough data captured to hold the GIOP header; don't try
3773 to interpret it as GIOP. */
3777 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3778 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3781 * because I have added extra elements in MessageHeader struct
3782 * for sub dissectors. -- FS
3785 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3787 if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
3789 /* Not a GIOP message. */
3794 if (check_col (pinfo->cinfo, COL_PROTOCOL))
3796 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3799 if (header.GIOP_version.major != GIOP_MAJOR ||
3800 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3802 /* Bad version number; should we note that and dissect the rest
3803 as data, or should we return FALSE on the theory that it
3804 might have been some other packet that happened to begin with
3805 "GIOP"? We shouldn't do *both*, so we return TRUE, for now.
3806 If we should return FALSE, we should do so *without* setting
3807 the "Info" column, *without* setting the "Protocol" column,
3808 and *without* adding anything to the protocol tree. */
3810 if (check_col (pinfo->cinfo, COL_INFO))
3812 col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3813 header.GIOP_version.major, header.GIOP_version.minor);
3817 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3818 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3819 proto_tree_add_text (clnp_tree, giop_header_tvb, 0, -1,
3820 "Version %u.%u not supported",
3821 header.GIOP_version.major,
3822 header.GIOP_version.minor);
3824 call_dissector(data_handle,payload_tvb, pinfo, tree);
3828 if (check_col (pinfo->cinfo, COL_INFO))
3830 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3831 header.GIOP_version.major, header.GIOP_version.minor,
3832 val_to_str(header.message_type, giop_message_types,
3833 "Unknown message type (0x%02x)"));
3836 stream_is_big_endian = is_big_endian (&header);
3838 if (stream_is_big_endian)
3839 message_size = pntohl (&header.message_size);
3841 message_size = pletohl (&header.message_size);
3845 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, 12, FALSE);
3846 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3847 proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3848 "Magic number: %s", GIOP_MAGIC);
3849 proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3851 header.GIOP_version.major,
3852 header.GIOP_version.minor);
3853 switch (minor_version)
3857 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3858 "Flags: 0x%02x (%s %s)",
3860 (stream_is_big_endian) ? "big-endian" : "little-endian",
3861 (header.flags & 0x02) ? " fragment" : "");
3864 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3865 "Byte ordering: %s-endian",
3866 (stream_is_big_endian) ? "big" : "little");
3870 } /* minor_version */
3872 proto_tree_add_uint_format (clnp_tree,
3873 hf_giop_message_type,
3874 giop_header_tvb, 7, 1,
3875 header.message_type,
3876 "Message type: %s", match_strval(header.message_type, giop_message_types));
3878 proto_tree_add_uint (clnp_tree,
3879 hf_giop_message_size,
3880 giop_header_tvb, 8, 4, message_size);
3885 if (check_col (pinfo->cinfo, COL_INFO))
3887 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3888 header.GIOP_version.major, header.GIOP_version.minor,
3889 match_strval(header.message_type, giop_message_types));
3893 switch (header.message_type)
3897 if(header.GIOP_version.minor < 2)
3899 dissect_giop_request_1_1 (payload_tvb, pinfo, tree,
3900 &header, stream_is_big_endian);
3904 dissect_giop_request_1_2 (payload_tvb, pinfo, tree,
3905 &header, stream_is_big_endian);
3912 if(header.GIOP_version.minor < 2)
3914 dissect_giop_reply (payload_tvb, pinfo, tree, &header,
3915 stream_is_big_endian);
3919 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree,
3920 &header, stream_is_big_endian);
3924 dissect_giop_cancel_request(payload_tvb, pinfo, tree,
3925 stream_is_big_endian);
3928 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
3929 stream_is_big_endian);
3932 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
3933 stream_is_big_endian);
3936 dissect_giop_fragment(payload_tvb, pinfo, tree,
3937 stream_is_big_endian);
3942 } /* switch message_type */
3946 * XXX - we should catch exceptions here, so that we can free
3947 * this if an exception is thrown.
3948 * We'd then have to forward the exception.
3950 if (header.exception_id != NULL)
3951 g_free(header.exception_id);
3957 proto_register_giop (void)
3959 static hf_register_info hf[] = {
3960 { &hf_giop_message_type,
3961 { "Message type", "giop.type",
3962 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
3965 { &hf_giop_message_size,
3966 { "Message size", "giop.len",
3967 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3971 { "Repository ID", "giop.repoid",
3972 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
3975 { &hf_giop_string_length,
3976 { "String Length", "giop.strlen",
3977 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3980 { &hf_giop_sequence_length,
3981 { "Sequence Length", "giop.seqlen",
3982 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3985 { &hf_giop_profile_id,
3986 { "Profile ID", "giop.profid",
3987 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
3992 { "IOR::type_id", "giop.typeid",
3993 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
3996 { &hf_giop_iiop_v_maj,
3997 { "IIOP Major Version", "giop.iiop_vmaj",
3998 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4001 { &hf_giop_iiop_v_min,
4002 { "IIOP Minor Version", "giop.iiop_vmin",
4003 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4006 { &hf_giop_endianess,
4007 { "Endianess", "giop.endianess",
4008 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4011 { &hf_giop_IIOP_tag,
4012 { "IIOP Component TAG", "giop.iioptag",
4013 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4017 { "IOR Profile TAG", "giop.iortag",
4018 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4022 { "TypeCode enum", "giop.TCKind",
4023 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4026 { &hf_giop_typecode_count,
4027 { "TypeCode count", "giop.tccount",
4028 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4031 { &hf_giop_typecode_default_used,
4032 { "default_used", "giop.tcdefault_used",
4033 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4036 { &hf_giop_typecode_digits,
4037 { "Digits", "giop.tcdigits",
4038 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4042 { &hf_giop_typecode_length,
4043 { "Length", "giop.tclength",
4044 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4047 { &hf_giop_typecode_max_length,
4048 { "Maximum length", "giop.tcmaxlen",
4049 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4052 { &hf_giop_typecode_member_name,
4053 { "TypeCode member name", "giop.tcmemname",
4054 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4057 { &hf_giop_typecode_name,
4058 { "TypeCode name", "giop.tcname",
4059 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4062 { &hf_giop_typecode_scale,
4063 { "Scale", "giop.tcscale",
4064 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4067 { &hf_giop_typecode_ValueModifier,
4068 { "ValueModifier", "giop.tcValueModifier",
4069 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4072 { &hf_giop_typecode_Visibility,
4073 { "Visibility", "giop.tcVisibility",
4074 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4079 { &hf_giop_type_boolean,
4080 { "TypeCode boolean data", "giop.tcboolean",
4081 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4084 { &hf_giop_type_char,
4085 { "TypeCode char data", "giop.tcchar",
4086 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4089 { &hf_giop_type_double,
4090 { "TypeCode double data", "giop.tcdouble",
4091 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4094 { &hf_giop_type_enum,
4095 { "TypeCode enum data", "giop.tcenumdata",
4096 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4100 * float as double ?? -- FIX
4103 { &hf_giop_type_float,
4104 { "TypeCode float data", "giop.tcfloat",
4105 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4108 { &hf_giop_type_long,
4109 { "TypeCode long data", "giop.tclongdata",
4110 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4113 { &hf_giop_type_octet,
4114 { "TypeCode octet data", "giop.tcoctet",
4115 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4118 { &hf_giop_type_short,
4119 { "TypeCode short data", "giop.tcshortdata",
4120 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4123 { &hf_giop_type_string,
4124 { "TypeCode string data", "giop.tcstring",
4125 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4128 { &hf_giop_type_ulong,
4129 { "TypeCode ulong data", "giop.tculongdata",
4130 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4133 { &hf_giop_type_ushort,
4134 { "TypeCode ushort data", "giop.tcushortdata",
4135 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4139 * IIOP Module - Chapter 15.10.2
4142 { &hf_giop_iiop_host,
4143 { "IIOP::Profile_host", "giop.iiop.host",
4144 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4148 { &hf_giop_iiop_port,
4149 { "IIOP::Profile_port", "giop.iiop.port",
4150 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4155 * IIOP ServiceContext
4158 { &hf_giop_iop_vscid,
4159 { "VSCID", "giop.iiop.vscid",
4160 FT_UINT32, BASE_HEX, NULL, 0xfffff000, "", HFILL }
4164 { &hf_giop_iop_scid,
4165 { "SCID", "giop.iiop.scid",
4166 FT_UINT32, BASE_HEX, NULL, 0x00000fff, "", HFILL }
4173 static gint *ett[] = {
4177 &ett_giop_cancel_request,
4178 &ett_giop_locate_request,
4179 &ett_giop_locate_reply,
4185 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4187 proto_register_field_array (proto_giop, hf, array_length (hf));
4188 proto_register_subtree_array (ett, array_length (ett));
4191 /* register init routine */
4193 register_init_routine( &giop_init); /* any init stuff */
4196 * Init the giop user module hash tables here, as giop users
4197 * will populate it via register_giop_user_module BEFORE my
4198 * own giop_init() is called.
4201 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4203 giop_module_keys = g_mem_chunk_new("giop_module_keys",
4204 sizeof(struct giop_module_key),
4205 giop_module_init_count * sizeof(struct giop_module_key),
4208 giop_module_vals = g_mem_chunk_new("giop_module_vals",
4209 sizeof(struct giop_module_val),
4210 giop_module_init_count * sizeof(struct giop_module_val),
4217 void proto_reg_handoff_giop (void) {
4218 data_handle = find_dissector("data");
4219 heur_dissector_add("tcp", dissect_giop, proto_giop);
4220 /* Support DIOP (GIOP/UDP) */
4221 heur_dissector_add("udp", dissect_giop, proto_giop);
4230 * Ref Corba v2.4.2 Chapter 13
4238 typedef unsigned long ProfileId;
4240 const ProfileId TAG_INTERNET_IOP = 0;
4241 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4243 struct TaggedProfile {
4245 sequence <octet> profile_data;
4250 sequence <TaggedProfile> profiles;
4253 typedef unsigned long ComponentId;
4255 struct TaggedComponent {
4257 sequence <octet> component_data;
4260 typedef sequence <TaggedComponent> MultipleComponentProfile;
4266 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4267 guint32 boundary, gboolean stream_is_big_endian) {
4270 guint32 seqlen_p; /* sequence length of profiles */
4273 proto_tree *tree = NULL; /* IOR tree */
4276 gchar *repobuf; /* for repository ID */
4280 /* create a subtree */
4283 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
4284 tree = proto_item_add_subtree (tf, ett_giop_ior);
4288 /* Get type_id == Repository ID */
4290 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4293 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4294 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4296 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4297 *offset-u_octet4,u_octet4,repobuf);
4302 * Register a cleanup function in case on of our tvbuff accesses
4303 * throws an exception. We need to clean up repobuf.
4304 * We can't free it yet, as we must wait until we have the object
4305 * key, as we have to add both to the hash table.
4307 CLEANUP_PUSH(g_free, repobuf);
4309 /* Now get a sequence of profiles */
4310 /* Get sequence length (number of elements) */
4312 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4314 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4315 *offset-sizeof(seqlen_p),4,seqlen_p);
4319 /* fetch all TaggedProfiles in this sequence */
4321 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4322 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4326 * We're done with repobuf, so we can call the cleanup handler to free
4327 * it, and then pop the cleanup handler.
4329 CLEANUP_CALL_AND_POP;
4333 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4334 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4336 guint32 seqlen_pd; /* sequence length of profile data */
4338 guint32 pidtag; /* profile ID TAG */
4340 gchar *profile_data; /* profile_data pointer */
4341 gchar *p_profile_data; /* printable profile_data pointer */
4343 guint32 new_boundary; /* for encapsulations encountered */
4344 gboolean new_big_endianess; /* for encapsulations encountered */
4346 /* Get ProfileId tag */
4348 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4351 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4352 *offset-sizeof(pidtag),4,pidtag);
4355 /* get sequence length, new endianness and boundary for encapsulation */
4357 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4358 stream_is_big_endian, boundary,
4359 &new_big_endianess, &new_boundary);
4361 /* return if zero length sequence */
4368 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4369 * decode it, otherwise just dump the octet sequence
4371 * also, store IOR in our objectkey hash
4373 * TODO - handle other TAGS
4377 case IOP_TAG_INTERNET_IOP:
4379 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4384 /* fetch all octets in this sequence , but skip endianess */
4386 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4388 /* Make a printable string */
4390 p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4393 proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4394 "Profile Data: %s", p_profile_data);
4397 g_free(p_profile_data);
4399 g_free(profile_data);
4410 * Decode IIOP IOR Profile
4411 * Ref Chap 15.7.2 in Corba Spec
4415 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4416 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4417 gboolean store_flag) {
4419 guint32 i; /* loop index */
4421 guint8 v_major,v_minor; /* IIOP sersion */
4423 guint32 u_octet4; /* u long */
4424 guint16 u_octet2; /* u short */
4425 guint32 seqlen; /* generic sequence length */
4426 guint32 seqlen1; /* generic sequence length */
4427 gchar *objkey; /* object key pointer */
4428 gchar *p_chars; /* printable characters pointer */
4431 /* Get major/minor version */
4433 v_major = get_CDR_octet(tvb,offset);
4434 v_minor = get_CDR_octet(tvb,offset);
4438 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4439 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4440 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4441 *offset-sizeof(v_minor),1,v_minor );
4447 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4450 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4451 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4453 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4454 *offset-u_octet4,u_octet4,buf);
4458 g_free(buf); /* dont forget */
4462 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4465 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4466 *offset-sizeof(u_octet2),2,u_octet2);
4470 /* Object Key - sequence<octet> object_key */
4472 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4475 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4476 *offset-sizeof(seqlen),4,seqlen);
4480 /* fetch all octets in this sequence */
4481 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4484 * Now we may have the Repository ID from earlier, as well
4485 * as the object key sequence and lengh. So lets store them in
4486 * our objectkey hash and free buffers.
4488 * But only insert if user is not clicking and repo id not NULL.
4494 if(!pinfo->fd->flags.visited)
4495 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4500 * No pinfo, but store anyway if flag set. eg: IOR read from file
4504 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4508 /* Make a printable string */
4510 p_chars = make_printable_string( objkey, seqlen );
4513 proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
4514 "Object Key: %s", p_chars);
4522 * Now see if if its v1.1 or 1.2, as they can contain
4523 * extra sequence of IOP::TaggedComponents
4536 /* sequence of IOP::TaggedComponents */
4537 /* Ref Chap 13 in Corba Spec */
4539 /* get sequence length */
4540 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4543 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4544 *offset-sizeof(seqlen),4,seqlen);
4547 for (i=0; i< seqlen; i++) {
4549 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4551 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4552 *offset-sizeof(u_octet4),4,u_octet4);
4555 /* get component_data */
4556 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4558 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4559 *offset-sizeof(seqlen1),4,seqlen1);
4563 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4566 /* Make a printable string of data */
4568 p_chars = make_printable_string(buf, seqlen1);
4570 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4571 "component_data: %s", p_chars);
4585 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4593 * 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, 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;
4652 gchar *p_context_data;
4655 guint32 vscid; /* Vendor Service context id */
4658 /* create a subtree */
4661 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "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; /* 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 );
4771 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4772 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4775 proto_tree_add_text(tree, tvb, *offset-8, 4,
4776 "Minor code value: %u", minor_code_value);
4777 proto_tree_add_text(tree, tvb, *offset-4, 4,
4778 "Completion Status: %u", completion_status);
4784 * Helper functions for dissecting TypeCodes
4786 * These functions decode the complex parameter lists
4787 * of TypeCodes as defined in the CORBA spec chapter 15.
4790 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4791 gboolean stream_is_big_endian, guint32 boundary) {
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) {
4920 guint32 new_boundary; /* new boundary for encapsulation */
4921 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4923 guint32 count; /* parameter count (of tuples) */
4924 guint32 seqlen; /* sequence length */
4925 guint32 i; /* loop index */
4927 /* get sequence length, new endianness and boundary for encapsulation */
4928 seqlen = get_CDR_encap_info(tvb, tree, offset,
4929 stream_is_big_endian, boundary,
4930 &new_stream_is_big_endian, &new_boundary);
4932 /* get repository ID */
4933 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4937 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4938 hf_giop_typecode_name);
4940 /* get count of tuples */
4941 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4943 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4944 *offset-sizeof(count),4,count);
4947 /* get all tuples */
4948 for (i=0; i< count; i++) {
4949 /* get member name */
4950 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4951 hf_giop_typecode_member_name);
4957 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4958 gboolean stream_is_big_endian, guint32 boundary,
4959 MessageHeader * header) {
4961 guint32 new_boundary; /* new boundary for encapsulation */
4962 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4964 guint32 u_octet4; /* unsigned int32 */
4966 guint32 seqlen; /* sequence length */
4968 /* get sequence length, new endianness and boundary for encapsulation */
4969 seqlen = get_CDR_encap_info(tvb, tree, offset,
4970 stream_is_big_endian, boundary,
4971 &new_stream_is_big_endian, &new_boundary);
4973 /* get element type */
4974 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4976 /* get max length */
4977 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4979 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
4980 *offset-sizeof(u_octet4),4,u_octet4);
4985 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4986 gboolean stream_is_big_endian, guint32 boundary,
4987 MessageHeader * header) {
4989 guint32 new_boundary; /* new boundary for encapsulation */
4990 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4992 guint32 u_octet4; /* unsigned int32 */
4994 guint32 seqlen; /* sequence length */
4996 /* get sequence length, new endianness and boundary for encapsulation */
4997 seqlen = get_CDR_encap_info(tvb, tree, offset,
4998 stream_is_big_endian, boundary,
4999 &new_stream_is_big_endian, &new_boundary);
5001 /* get element type */
5002 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5005 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5007 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5008 *offset-sizeof(u_octet4),4,u_octet4);
5013 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5014 gboolean stream_is_big_endian, guint32 boundary,
5015 MessageHeader * header) {
5017 guint32 new_boundary; /* new boundary for encapsulation */
5018 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5020 guint32 seqlen; /* sequence length */
5022 /* get sequence legnth, new endianness and boundary for encapsulation */
5023 seqlen = get_CDR_encap_info(tvb, tree, offset,
5024 stream_is_big_endian, boundary,
5025 &new_stream_is_big_endian, &new_boundary);
5027 /* get repository ID */
5028 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5032 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5033 hf_giop_typecode_name);
5035 /* get ??? (noname) TypeCode */
5036 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5041 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5042 gboolean stream_is_big_endian, guint32 boundary,
5043 MessageHeader * header) {
5045 guint32 new_boundary; /* new boundary for encapsulation */
5046 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5048 guint32 count; /* parameter count (of tuples) */
5049 guint32 seqlen; /* sequence length */
5050 guint32 i; /* loop index */
5052 /* get sequence length, new endianness and boundary for encapsulation */
5053 seqlen = get_CDR_encap_info(tvb, tree, offset,
5054 stream_is_big_endian, boundary,
5055 &new_stream_is_big_endian, &new_boundary);
5057 /* get repository ID */
5058 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5062 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5063 hf_giop_typecode_name);
5065 /* get count of tuples */
5066 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5068 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5069 *offset-sizeof(count),4,count);
5072 /* get all tuples */
5073 for (i=0; i< count; i++) {
5074 /* get member name */
5075 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5076 hf_giop_typecode_member_name);
5078 /* get member type */
5079 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5085 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5086 gboolean stream_is_big_endian, guint32 boundary,
5087 MessageHeader * header) {
5089 guint32 new_boundary; /* new boundary for encapsulation */
5090 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5092 gint16 s_octet2; /* signed int16 */
5094 guint32 count; /* parameter count (of tuples) */
5095 guint32 seqlen; /* sequence length */
5096 guint32 i; /* loop index */
5098 /* get sequence length, new endianness and boundary for encapsulation */
5099 seqlen = get_CDR_encap_info(tvb, tree, offset,
5100 stream_is_big_endian, boundary,
5101 &new_stream_is_big_endian, &new_boundary);
5103 /* get repository ID */
5104 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5108 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5109 hf_giop_typecode_name);
5111 /* get ValueModifier */
5112 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5114 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5115 *offset-sizeof(s_octet2),2,s_octet2);
5118 /* get conrete base */
5119 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5121 /* get count of tuples */
5122 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5124 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5125 *offset-sizeof(count),4,count);
5128 /* get all tuples */
5129 for (i=0; i< count; i++) {
5130 /* get member name */
5131 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5132 hf_giop_typecode_member_name);
5134 /* get member type */
5135 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5137 /* get Visibility */
5138 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5140 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5141 *offset-sizeof(s_octet2),2,s_octet2);
5148 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5149 gboolean stream_is_big_endian, guint32 boundary,
5150 MessageHeader * header) {
5152 guint32 new_boundary; /* new boundary for encapsulation */
5153 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5155 guint32 seqlen; /* sequence length */
5157 /* get sequence length, new endianness and boundary for encapsulation */
5158 seqlen = get_CDR_encap_info(tvb, tree, offset,
5159 stream_is_big_endian, boundary,
5160 &new_stream_is_big_endian, &new_boundary);
5162 /* get repository ID */
5163 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5167 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5168 hf_giop_typecode_name);
5170 /* get ??? (noname) TypeCode */
5171 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5175 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5176 gboolean stream_is_big_endian, guint32 boundary) {
5178 guint32 new_boundary; /* new boundary for encapsulation */
5179 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5181 guint32 seqlen; /* sequence length */
5183 /* get sequence length, new endianness and boundary for encapsulation */
5184 seqlen = get_CDR_encap_info(tvb, tree, offset,
5185 stream_is_big_endian, boundary,
5186 &new_stream_is_big_endian, &new_boundary);
5188 /* get repository ID */
5189 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5193 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5194 hf_giop_typecode_name);
5199 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5200 gboolean stream_is_big_endian, guint32 boundary) {
5202 guint32 new_boundary; /* new boundary for encapsulation */
5203 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5205 guint32 seqlen; /* sequence length */
5207 /* get sequence length, new endianness and boundary for encapsulation */
5208 seqlen = get_CDR_encap_info(tvb, tree, offset,
5209 stream_is_big_endian, boundary,
5210 &new_stream_is_big_endian, &new_boundary);
5212 /* get repository ID */
5213 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5217 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5218 hf_giop_typecode_name);
5222 /* Typecode parameter lists are encoded as encapsulations and
5223 * this function gets the encapsulation information; see
5224 * CORBA spec chapter 15
5227 * Renamed to get_CDR_encap_info() for any encapsulation
5228 * we come across, useful helper function
5230 * Also, should return immediately if seqlen == 0.
5231 * ie: Forget about trying to grab endianess for
5232 * zero length sequence.
5234 * Caller must always check seqlen == 0, and not assume its value
5237 * Note: there seemed to be considerable confusion in corba
5238 * circles as to the correct interpretation of encapsulations,
5239 * and zero length sequences etc, but this is our best bet at the
5246 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5247 gboolean old_stream_is_big_endian, guint32 old_boundary,
5248 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5250 guint32 seqlen; /* sequence length */
5251 guint8 giop_endianess;
5253 /* Get sequence length of parameter list */
5254 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5256 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5257 *offset-sizeof(seqlen),4,seqlen);
5263 * seqlen == 0, implies no endianess and no data
5264 * so just return. Populate new_boundary_ptr and
5265 * new_stream_is_big_endian_ptr with current (old)
5266 * values, just to keep everyone happy. -- FS
5272 *new_boundary_ptr = old_boundary;
5273 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5279 /* Start of encapsulation of parameter list */
5280 *new_boundary_ptr = *offset; /* remember */
5281 giop_endianess = get_CDR_octet(tvb,offset);
5283 *new_stream_is_big_endian_ptr = ! giop_endianess;
5286 * Glib: typedef gint gboolean;
5287 * ie: It is not a guint8, so cannot use sizeof to correctly
5293 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5294 *offset-1,1,giop_endianess);
5304 * gets a TypeCode complex string parameter and
5305 * displays it in the relevant tree.
5308 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5309 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5311 guint32 u_octet4; /* unsigned int32 */
5312 gchar *buf; /* ptr to string buffer */
5315 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5318 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5319 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5321 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5325 g_free(buf); /* dont forget */
5330 * For a given data type, given by a TypeCode gets the associated data
5331 * and displays it in the relevant tree.
5334 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5335 gboolean stream_is_big_endian, guint32 boundary,
5336 MessageHeader * header, guint32 data_type ) {
5338 gboolean my_boolean; /* boolean */
5340 gint8 s_octet1; /* signed int8 */
5341 guint8 u_octet1; /* unsigned int8 */
5343 gint16 s_octet2; /* signed int16 */
5344 guint16 u_octet2; /* unsigned int16 */
5346 gint32 s_octet4; /* signed int32 */
5347 guint32 u_octet4; /* unsigned int32 */
5349 gdouble my_double; /* double */
5350 gfloat my_float; /* float */
5352 gchar *buf = NULL; /* ptr to string buffer */
5354 /* Grab the data according to data type */
5356 switch (data_type) {
5358 /* nothing to decode */
5361 /* nothing to decode */
5364 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5366 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5367 *offset-sizeof(s_octet2),2,s_octet2);
5371 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5373 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5374 *offset-sizeof(s_octet4),4,s_octet4);
5378 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5380 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5381 *offset-sizeof(u_octet2),2,u_octet2);
5385 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5387 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5388 *offset-sizeof(u_octet4),4,u_octet4);
5392 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5394 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5395 *offset-sizeof(my_float),4,my_float);
5399 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5401 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5402 *offset-sizeof(my_double),8,my_double);
5406 my_boolean = get_CDR_boolean(tvb,offset);
5408 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5409 *offset-1,1,my_boolean);
5413 u_octet1 = get_CDR_char(tvb,offset);
5415 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5416 *offset-sizeof(u_octet1),1,u_octet1);
5420 u_octet1 = get_CDR_octet(tvb,offset);
5422 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5423 *offset-sizeof(u_octet1),1,u_octet1);
5427 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5430 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5441 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5443 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5444 *offset-sizeof(u_octet4),4,u_octet4);
5448 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5450 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5451 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5453 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5454 *offset-u_octet4,u_octet4,buf);
5458 g_free(buf); /* dont forget */
5475 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5478 * XXX - can any of these throw an exception?
5479 * If so, we need to catch the exception and free "buf".
5481 if (s_octet1 < 0) { /* no size to add to tree */
5482 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5483 *offset+s_octet1,(-s_octet1),buf);
5485 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5486 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5487 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5488 *offset-s_octet1,s_octet1,buf);
5492 g_free(buf); /* dont forget */
5495 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5498 * XXX - can any of these throw an exception?
5499 * If so, we need to catch the exception and free "buf".
5501 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5502 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5503 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5504 *offset-u_octet4,u_octet4,buf);
5507 g_free(buf); /* dont forget */
5517 case tk_abstract_interface:
5520 g_warning("giop: Unknown typecode data type %u \n", data_type);