2 * Routines for CORBA GIOP/IIOP packet disassembly
5 * Laurent Deniel <deniel@worldnet.fr>
6 * Craig Rodrigues <rodrigc@mediaone.net>
8 * GIOP API extensions by,
9 * Frank Singleton <frank.singleton@ericsson.com>
10 * Trevor Shepherd <eustrsd@am1.ericsson.se>
12 * $Id: packet-giop.c,v 1.48 2001/08/28 07:19:47 guy Exp $
14 * Ethereal - Network traffic analyzer
15 * By Gerald Combs <gerald@ethereal.com>
16 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 * 1. heuristic giop dissector table [started]
37 * 2. GUI options, see 20
38 * 3. Remove unneccessary reply_status in heuristic dissector calls (now
39 * part of MessageHeader) [done]
40 * 4. get_CDR_xxx should be passed an alignment offset value
41 * rather than GIOP_HEADER_SIZE, as alignment can also change in a
42 * octet stream when eg: encapsulation is used [done]
43 * 5. GIOP users should eventually get there own tvbuff, and
44 * not rely on the GIOP tvbuff, more robust
45 * 6. get_CDR_string,wchar,wstring etc should handle different
46 * GIOP versions [started]
47 * 7. Fix situation where req_id is not unique in a logfile [done, use FN/MFN, needs improving.]
49 * 8. Keep request_1_2 in step with request_1_1 [started]
50 * 9. Explicit module name dissection [done]
51 * 10. Decode IOR and put in a useful struct [IOR decode started]
52 * 11. Fix encapsulation of IOR etc and boundary [done]
53 * 12. handle get_CDR_typeCode() [started]
54 * 13. Handle different IOR profiles
55 * 14. Change printable_string to RETURN a new string, not to modify the old.
56 * or, new function, make_printable_string [done, make_printable_string]
58 * 15. Handle "TCKind", and forget about eg: enum translation to symbolic values
59 * otherwise need knowledge of sub dissectors data - YUK [done]
60 * 16. Handle multiple RepoId representations, besides IDL:Echo:1.0 (see 13.)
61 * 17. Pass subset of RepoID to explicit dissector.
62 * eg : If IDL:Mod1/Mod2/Int3:1.0 then pass "Mod1/Mode2/Int3" to sub dissector[done]
63 * 18. Better hashing algorithms
64 * 19. Handle hash collision properly .
65 * 20. Allow users to paste a stringified IOR into the GUI, and tie it
67 * 21. Add complete_request_packet_list and complete_reply_packet_hash.[done]
68 * 22. Handle case where users click in any order, AND try and match
69 * REPLY msg to the correct REQUEST msg when we have a request_id collision.[done]
70 * 23. Clean up memory management for all those g_malloc's etc
71 * 24. register_giop_user_module could return a key for every distinct Module/Interface
72 * the sub_dissector uses. So, instead of strcmp()'s when handling the
73 * namespace of an operation, we could have a lookup table instead.
74 * 25. A few typedefs in the right place.
75 * 26 Improve handling of gchar * and use const gchar * where possible.
76 * 27. Read/write IOR etc to/from file, allows objkey hash to be built from
77 * external data [read done, write incomplete]
78 * 28. Call sub dissector only if tvb_offset_exists(). [Done, this is checked
79 * inside try_explicit_giop_dissector() ]
81 * 29. Make add/delete routine for objkey hash as it may be useful when say reading
82 * stringified IOR's from a file to add them to our hash. ie: There are other ways
83 * to populate our object key hash besides REPLY's to RESOLVE(request) [done]
85 * 30. Add routine to encode/decode stringified IOR's [decode done]
86 * 31. Add routine to read IOR's from file [done]
87 * 32. TypeCode -none-, needs decoding.
88 * 33. Complete dissect_data_for_typecode.
89 * 34. For complex TypeCodes need to check final offset against original offset + sequence length.
90 * 35. Update REQUEST/REPLY 1_2 according to IDL (eg; ServiceContextList etc).
91 * 36. Adding decode_ServiceContextList, incomplete.
92 * 37. Helper functions should not ALWAYS rely on header to find current endianess. It should
93 * be passed from user, eg Use stream_is_big_endian. [started]
94 * 38. Remove unwanted/unused function parameters, see decode_IOR [started]
95 * 40. Add sequence <IOP::TaggedComponent> components to IIOP IOR profile. Perhaps
96 * decode_IOP_TaggedComponents as a helper function. [done - NOT helper]
98 * 41. Make important field searchable from Message header. ie: Remove add_text_
99 * 42. Use sub-tree for decode_ServiceContextList, looks better.
100 * 43. dissect_reply_body, no exception dissector calls
101 * - call subdiss directly, as we already have handle.
102 * - add repoid to heuristic call also.
104 * 44. typedef using xxx_t in .h file.
105 * 45. Subdissectors should not be passed MessageHeader to find endianness and
106 * version, they should be passed directly ?
107 * 46. get_CDR_wchar and wstring need wide chars decoded (just dumped in
108 * any readable form at present, not handled well at all, suggestions welcome -- FS
109 * 47. Change ...add_text to ...add_xxx (ie use hf fields).
111 * 48. BUG - file load with a GIOP filter set, causes the FN/MFN data struct to be
112 * not initiated properly. Hit "Reload" as a workaround, til I fix this -- FS
119 * Intended Decode strategy:
120 * =========================
124 * REQUEST: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
125 * and populate complete_request_packet_hash
127 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
132 * REQUEST: FN -> giop_sub_handle_t directly (via complete_request_packet_hash)
134 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
135 * (via complete_request_packet_hash
141 * 1. Request_ID's are unique only per connection.
143 * 2. You must be monitoring the network when the client does
144 * a REQUEST(resolve), otherwise I have no knowledge of the
145 * association between object_key and REPOID. I could talk to
146 * a Nameserver, but then I would start "generating" packets.
147 * This is probably not a good thing for a protocol analyser.
148 * Also, how could I decode logfiles offline.
150 * TODO -- Read stringified IORs from an input file.[done]
152 * 3. User clicks (REQUEST) is currently handle the same as
153 * the initial pass handling.
155 * ie: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
160 * Important Data Structures:
165 * This is a hash table that maps IDL Module/Interface Names (Key)
166 * to sub_dissector handles, giop_sub_handle_t. It is populated
167 * by subdissectors, via register_giop_user_module(). This
168 * table is used when we have a REPOID, and explicitly wish to
169 * call the subdissector that has registered responsibility for
170 * that IDL module/interface.
176 * This singly linked list is used to hold entries for
177 * heuristic based subdissectors. It is populated by sub_dissectors
178 * wishing to be called via heuristic mechanisms. They do this
179 * via the register_giop_user() function.
185 * This hash table maps object_key's (key) onto REPOID's (val).
186 * Once a client has REQUEST(resolve) an object , it knows about
187 * an object (interface) via its object_key (see IOR). So in order to follow
188 * packets that contain an object_key only, and to be able to forward it
189 * to the correct explicit subdissector, we need this table.
191 * So, I listen in on REQUEST(resolve) messages between client and
192 * Nameserver, and store the respones (REPLY/Objkey,Repo_ID) here.
194 * Also, stringified IOR's can be read from a file "IOR.txt" and used
195 * to populate this hash also.
198 * Other Data structures
199 * =======================
201 * These structures have been added to minimise the possibility
202 * of incorrectly interpreted packets when people click all
203 * over the place, in no particular order, when the request_id's are
204 * not unique as captured. If all request_is'd are unique, as captured, then
205 * we would not have to deal with this problem.
208 * When the logfile or packets are initially being processed, I will
209 * build 2 structures. The intent is to be able to map a REPLY message
210 * back to the most recent REQUEST message with the same Request_ID
211 * (TODO and matching port and IP address ??)
217 * MFN - Matching Frame Number
220 * complete_request_packet_list
221 * ----------------------------
223 * This is a list that contains ALL the FN's that are REQUEST's, along with
224 * operation,request_id and giop_sub_handle_t
226 * complete_reply_packet_hash
227 * --------------------------
229 * This is a hash table. It is populated with FN (key) and MFN (val).
230 * This allows me to handle the case, where if you click on any REPLY
231 * message, I can lookup the matching request. This can improve
232 * the match rate between REQUEST and REPLY when people click in
233 * any old fashion, but is NOT foolproof.
235 * The algorithm I use to populate this hash during initial pass,
238 * If packet is a REPLY, note the reqid, and then traverse backwards
239 * through the complete_request_packet_list from its tail, looking
240 * for a FN that has the same Request_id. Once found, take the found FN
241 * from complete_reply_packet_hash, and insert it into the MFN field
242 * of the complete_reply_packet_hash.
245 * See TODO for improvements to above algorithm.
247 * So now when people click on a REQUEST packet, I can call lookup the
248 * giop_sub_handle_t directly from complete_request_packet_list.
250 * And, when they click on a REPLY, I grab the MFN of this FN from
251 * complete_reply_packet_hash, then look that up in the complete_request_packet_list
252 * and call the sub_dissector directly.
254 * So, how do I differentiate between the initial processing of incoming
255 * packets, and a user clickin on one ? Good question.
257 * I leverage the pinfo_fd->flags.visited on a per frame
260 * To quote from the ever helpful development list
262 * " When a capture file is initially loaded, all "visited" flags
263 * are 0. Ethereal then makes the first pass through file,
264 * sequentially dissecting each packet. After the packet is
265 * dissected the first time, "visited" is 1. (See the end of
266 * dissect_packet() in epan/packet.c; that's the code that
267 * sets "visited" to 1).
269 * By the time a user clicks on a packet, "visited" will already
270 * be 1 because Ethereal will have already done its first pass
271 * through the packets.
273 * Reload acts just like a normal Close/Open, except that it
274 * doesn't need to ask for a filename. So yes, the reload button
275 * clears the flags and re-dissects the file, just as if the file
276 * had been "opened". "
285 #ifdef HAVE_SYS_TYPES_H
286 # include <sys/types.h>
295 #ifdef NEED_STRERROR_H
296 #include "strerror.h"
300 #include "packet-giop.h"
303 * This affects how we handle context_data inside ServiceContext structs.
304 * According to CORBA 2.4.2, Context data is encapsulated in octet sequences,
305 * but so far I haven't seen the that on the wire. But, maybe its me -- FS
309 #define CONTEXT_DATA_IS_ENCAPSULATED 0
313 * Set to 1 for DEBUG output - TODO make this a runtime option
321 * ------------------------------------------------------------------------------------------+
322 * Private Helper function Declarations
323 * ------------------------------------------------------------------------------------------+
327 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
328 guint32 boundary, gboolean new_endianess, gchar *repobuf,
329 gboolean store_flag);
331 static void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
332 gboolean stream_is_be, guint32 boundary);
334 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
335 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf);
337 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
338 guint32 boundary, gboolean stream_is_big_endian );
340 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
341 gboolean stream_is_big_endian,
344 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
345 gboolean stream_is_big_endian, guint32 boundary,
346 MessageHeader * header);
348 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
349 gboolean stream_is_big_endian, guint32 boundary,
350 MessageHeader * header);
352 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
353 gboolean stream_is_big_endian, guint32 boundary,
354 MessageHeader * header );
356 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
357 gboolean stream_is_big_endian, guint32 boundary,
358 MessageHeader * header);
360 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
361 gboolean stream_is_big_endian, guint32 boundary,
362 MessageHeader * header);
364 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
365 gboolean stream_is_big_endian, guint32 boundary,
366 MessageHeader * header);
368 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
369 gboolean stream_is_big_endian, guint32 boundary,
370 MessageHeader * header);
372 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
373 gboolean stream_is_big_endian, guint32 boundary,
374 MessageHeader * header);
376 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
377 gboolean stream_is_big_endian, guint32 boundary,
378 MessageHeader * header);
380 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
381 gboolean stream_is_big_endian, guint32 boundary,
382 MessageHeader * header);
384 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
385 gboolean stream_is_big_endian, guint32 boundary,
386 MessageHeader * header);
388 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
389 gboolean stream_is_big_endian, guint32 boundary,
390 MessageHeader * header);
393 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
394 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
396 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
397 gboolean stream_is_big_endian, guint32 boundary,
398 MessageHeader * header, guint32 data_type );
404 * ------------------------------------------------------------------------------------------+
405 * Data/Variables/Structs
406 * ------------------------------------------------------------------------------------------+
410 static int proto_giop = -1;
411 static int hf_giop_message_type = -1;
412 static int hf_giop_message_size = -1;
413 static int hf_giop_repoid = -1;
414 static int hf_giop_string_length = -1;
415 static int hf_giop_sequence_length = -1;
416 static int hf_giop_profile_id = -1;
417 static int hf_giop_type_id = -1;
418 static int hf_giop_iiop_v_maj = -1;
419 static int hf_giop_iiop_v_min = -1;
420 static int hf_giop_endianess = -1; /* esp encapsulations */
421 static int hf_giop_IOR_tag = -1;
422 static int hf_giop_IIOP_tag = -1;
424 static int hf_giop_TCKind = -1;
425 static int hf_giop_typecode_count = -1;
426 static int hf_giop_typecode_default_used = -1;
427 static int hf_giop_typecode_digits = -1;
428 static int hf_giop_typecode_length = -1;
429 static int hf_giop_typecode_max_length = -1;
430 static int hf_giop_typecode_member_name = -1;
431 static int hf_giop_typecode_name = -1;
432 static int hf_giop_typecode_scale = -1;
433 static int hf_giop_typecode_ValueModifier = -1;
434 static int hf_giop_typecode_Visibility = -1;
436 static int hf_giop_type_boolean = -1;
437 static int hf_giop_type_char = -1;
438 static int hf_giop_type_double = -1;
439 static int hf_giop_type_enum = -1;
440 static int hf_giop_type_float = -1;
441 static int hf_giop_type_long = -1;
442 static int hf_giop_type_octet = -1;
443 static int hf_giop_type_short = -1;
444 static int hf_giop_type_string = -1;
445 static int hf_giop_type_ulong = -1;
446 static int hf_giop_type_ushort = -1;
448 static int hf_giop_iiop_host = -1;
449 static int hf_giop_iiop_port = -1;
450 static int hf_giop_iop_vscid = -1;
451 static int hf_giop_iop_scid = -1;
457 static gint ett_giop = -1;
458 static gint ett_giop_reply = -1;
459 static gint ett_giop_request = -1;
460 static gint ett_giop_cancel_request = -1;
461 static gint ett_giop_locate_request = -1;
462 static gint ett_giop_locate_reply = -1;
463 static gint ett_giop_fragment = -1;
465 static gint ett_giop_scl = -1; /* ServiceContextList */
466 static gint ett_giop_ior = -1; /* IOR */
471 static const value_string giop_endianess_vals[] = {
472 { 0x0, "Big Endian" },
473 { 0x1, "Little Endian" },
477 static const value_string sync_scope[] = {
478 { 0x0, "SYNC_NONE" },
479 { 0x1, "SYNC_WITH_TRANSPORT"},
480 { 0x2, "SYNC_WITH_SERVER"},
481 { 0x3, "SYNC_WITH_TARGET"},
487 static const value_string profile_id_vals[] = {
488 { 0x0, "TAG_INTERNET_IOP" },
489 { 0x1, "TAG_MULTIPLE_COMPONENTS"},
490 { 0x2, "TAG_SCCP_IOP"},
494 static const value_string giop_message_types[] = {
497 { 0x2, "CancelRequest"},
498 { 0x3, "LocateRequest"},
499 { 0x4, "LocateReply"},
500 { 0x5, "CloseConnection"},
501 { 0x6, "MessageError"},
506 static const value_string giop_locate_status_types[] = {
507 { 0x0, "Unknown Object" },
508 { 0x1, "Object Here"},
509 { 0x2, "Object Forward"},
510 { 0x3, "Object Forward Perm"},
511 { 0x4, "Loc System Exception"},
512 { 0x5, "Loc Needs Addressing Mode"},
516 static const value_string tckind_vals[] = {
529 { 12, "tk_TypeCode"},
530 { 13, "tk_Principal"},
536 { 19, "tk_sequence"},
540 { 23, "tk_longlong"},
541 { 24, "tk_ulonglong"},
542 { 25, "tk_longdouble"},
547 { 30, "tk_value_box"},
549 { 32, "tk_abstract_interface"},
555 #define GIOP_MAGIC "GIOP"
558 * TAGS for IOR Profiles
560 * Chapter 13 Corba 2.4.2
564 #define IOP_TAG_INTERNET_IOP 0
565 #define IOP_TAG_MULTIPLE_COMPONENTS 1
568 /* Max Supported versions */
570 static const guint GIOP_MAJOR = 1;
571 static const guint GIOP_MINOR = 2;
574 static const int KeyAddr = 0;
575 static const int ProfileAddr = 1;
576 static const int ReferenceAddr = 2;
580 static const value_string reply_status_types[] = {
581 { NO_EXCEPTION, "No Exception" } ,
582 { USER_EXCEPTION, "User Exception" } ,
583 { SYSTEM_EXCEPTION, "System Exception" } ,
584 { LOCATION_FORWARD, "Location Forward" } ,
585 { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
586 { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
592 typedef enum LocateStatusType
597 OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
598 LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
599 LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
603 typedef struct LocateReplyHeader
606 guint32 locate_status;
612 * DATA - complete_request_list
615 static GList *giop_complete_request_list;
617 struct comp_req_list_entry {
618 guint32 fn; /* frame number */
619 gchar * operation; /* echo echoString */
620 giop_sub_handle_t *subh; /* handle to sub dissector */
621 guint32 reqid; /* request id */
622 gchar * repoid; /* repository ID */
625 typedef struct comp_req_list_entry comp_req_list_entry_t;
629 * DATA - complete_reply_hash
631 * Maps reply FN to request MFN
634 static int complete_reply_hash_count = 1000; /* storage size for our permanent data */
635 /* ie: 1000 entries -- needs tweaking -- FS */
637 struct complete_reply_hash_key {
638 guint32 fn; /* reply frame number */
641 struct complete_reply_hash_val {
642 guint32 mfn; /* matching frame number (request) */
645 GHashTable *giop_complete_reply_hash = NULL; /* hash */
646 GMemChunk *giop_complete_reply_keys = NULL; /* key storage */
647 GMemChunk *giop_complete_reply_vals = NULL; /* val storage */
651 * DATA - Module Hash stuff to store data from register_giop_user_module
653 * ie: module (or interface ?) name, and ptr to sub_dissector handle
655 * With this knowledge, we can call a sub dissector directly,
658 * objkey -> repoid -> sub_dissector via registered module/interface
663 static int giop_module_init_count = 100; /* storage size for our permanent data */
664 /* ie: 100 entries -- needs tweaking -- FS */
666 struct giop_module_key {
667 gchar *module; /* module (interface?) name */
670 struct giop_module_val {
671 giop_sub_handle_t *subh; /* handle to sub dissector */
674 GHashTable *giop_module_hash = NULL; /* hash */
675 GMemChunk *giop_module_keys = NULL; /* key storage */
676 GMemChunk *giop_module_vals = NULL; /* val storage */
680 * DATA - GSList to store list of function (dissector) pointers.
681 * for heuristic dissection.
685 static GSList *giop_sub_list = NULL;
688 * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
689 * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
691 * With this knowledge, we can call a sub dissector directly later
694 * objkey -> repoid -> sub_dissector via registered module/interface
696 * rather than heuristic calls that do not provide operation context.
697 * (unless we pass the RepoID for a given objkey -- hmmm)
702 * Interesting operation list, add more if you want to save
706 static const char giop_op_resolve[] = "resolve";
707 static const char giop_op_bind_new_context[] = "bind_new_context";
708 static const char giop_op_bind[] = "bind";
711 * Enums for interesting local operations, that we may need to monitor
712 * with their subsequent replies
717 request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
718 request_bind_new_context_op_val, /* bind_new_context */
719 request_bind_op_val, /* bind */
720 request_get_INIT_op_val, /* finding Nameserver */
726 * hash for mapping object keys onto object namespaces, so
727 * I can call the correct dissector.
733 * Where did I get the IOR from.
737 req_res = 0, /* REQUEST (resolve) */
738 file, /* stringified IOR' in a file */
742 typedef enum ior_src ior_src_t;
747 * Enums for my lists and hash's
750 enum collection_data {
751 cd_heuristic_users = 0,
754 cd_complete_request_list,
755 cd_complete_reply_hash
758 typedef enum collection_data collection_data_t;
762 static int giop_objkey_init_count = 100; /* storage size for our permanent data */
763 /* ie: 100 entries -- needs tweaking -- FS */
765 struct giop_object_key {
766 guint8 *objkey; /* ptr to object key */
767 guint32 objkey_len; /* length */
770 struct giop_object_val {
771 guint8 *repo_id; /* ptr to Repository ID string */
772 ior_src_t src; /* where did Iget this IOR from */
775 GHashTable *giop_objkey_hash = NULL; /* hash */
776 GMemChunk *giop_objkey_keys = NULL; /* key storage */
777 GMemChunk *giop_objkey_vals = NULL; /* val storage */
782 * ------------------------------------------------------------------------------------------+
783 * Private helper functions
784 * ------------------------------------------------------------------------------------------+
790 * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
793 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
794 GList * newlist_start;
795 comp_req_list_entry_t * entry = NULL;
798 entry = g_malloc(sizeof(comp_req_list_entry_t));
799 opn = g_strdup(op); /* duplicate operation for storage */
802 entry->reqid = reqid;
804 entry->operation = opn;
805 entry->repoid = NULL; /* dont have yet */
807 newlist_start = g_list_append (list, entry); /* append */
809 return newlist_start;
814 * Used to find an entry with matching Frame Number FN
815 * in the complete_request_list list.
818 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
820 GList * element; /* entry in list */
821 comp_req_list_entry_t * entry_ptr = NULL;
823 element = g_list_last(giop_complete_request_list); /* start from last */
825 while(element) { /* valid list entry */
826 entry_ptr = element->data; /* grab data pointer */
827 if (entry_ptr->fn == fn) { /* similar FN */
830 element = g_list_previous(element); /* try next previous */
833 return NULL; /* no match so return NULL */
838 * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
840 * Call this when you know a FN and matching giop_sub_handle_t and repoid
842 * This is done in say, try_explicit_dissector for example.
846 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
848 comp_req_list_entry_t * entry = NULL;
849 entry = find_fn_in_list(fn); /* grab FN data entry */
853 entry->repoid = g_strdup(repoid); /* copy and store */
861 /* giop_complete_reply_hash "EQUAL" Functions */
863 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
864 struct complete_reply_hash_key *mk1 = (struct complete_reply_hash_key *)v;
865 struct complete_reply_hash_key *mk2 = (struct complete_reply_hash_key *)w;
867 if (mk1->fn == mk2->fn) {
871 return 0; /* found differences */
874 /* giop_complete_reply_hash "HASH" Functions */
876 static guint32 complete_reply_hash_fn(gconstpointer v) {
877 guint32 val; /* init hash value */
878 struct complete_reply_hash_key *key = (struct complete_reply_hash_key *)v;
880 val = key->fn; /* simple and unique */
887 * Insert the FN and MFN together in our complete_reply_hash.
890 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
892 struct complete_reply_hash_key key, *new_key;
893 struct complete_reply_hash_val *val = NULL;
897 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
900 return; /* FN collision */
903 new_key = g_mem_chunk_alloc(giop_complete_reply_keys);
904 new_key->fn = fn; /* save FN */
906 val = g_mem_chunk_alloc(giop_complete_reply_vals);
907 val->mfn = mfn; /* and MFN */
909 g_hash_table_insert(giop_complete_reply_hash, new_key, val);
914 * Find the MFN values from a given FN key.
915 * Assumes the complete_reply_hash is already populated.
918 static guint32 get_mfn_from_fn(guint32 fn) {
920 struct complete_reply_hash_key key;
921 struct complete_reply_hash_val *val = NULL;
922 guint32 mfn = fn; /* save */
925 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
928 mfn = val->mfn; /* grab it */
931 return mfn; /* mfn or fn if not found */
936 * Attempt to find the MFN for this FN, and return it.
937 * Return MFN if found, or just FN if not. This is
938 * only used when we are building
941 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
943 GList * element; /* last entry in list */
944 comp_req_list_entry_t * entry_ptr = NULL;
946 /* Need Some pretty snappy code */
948 /* Loop back from current end of complete_request_list looking for */
949 /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
952 * As this routine is only called during initial pass of data,
953 * and NOT when a user clicks, it is ok to start from Current
954 * end of complete_request_list when searching for a match.
955 * As that list is bing populated in the same order as FN's
958 * Also, can make check for same reqid more detailed, but I start
959 * with reqid. Could add say port or address checks etc later ??
963 element = g_list_last(giop_complete_request_list); /* get last */
965 while(element) { /* valid list entry */
966 entry_ptr = element->data; /* grab data pointer */
967 if (entry_ptr->reqid == reqid) { /* similar reqid */
968 return entry_ptr->fn; /* return MFN */
970 element = g_list_previous(element); /* try next previous */
973 return fn; /* no match so return FN */
977 /* Module Hash "EQUAL" Functions */
979 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
980 struct giop_module_key *mk1 = (struct giop_module_key *)v;
981 struct giop_module_key *mk2 = (struct giop_module_key *)w;
983 if (!strcmp(mk1->module, mk2->module)) {
987 return 0; /* found differences */
990 /* Module Hash "HASH" Functions */
992 static guint32 giop_hash_module_hash(gconstpointer v) {
995 guint32 val = 0; /* init hash value */
997 struct giop_module_key *key = (struct giop_module_key *)v;
1000 * Hmm, try this simple hashing scheme for now.
1001 * ie: Simple summation, FIX later -- FS
1006 len = strlen(key->module);
1008 for (i=0; i<len; i++) {
1009 val += (guint8) key->module[i];
1018 * ------------------------------------------------------------------------------------------+
1019 * Public Utility functions
1020 * ------------------------------------------------------------------------------------------+
1027 * Routine to allow giop users to register their sub dissector function, name, and
1028 * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1029 * value returned from their proto_register_protocol(), so we can enable/disbale it
1030 * through the GUI (edit protocols).
1032 * This is used by try_explicit_giop_dissector() to find the
1033 * correct sub-dissector.
1037 void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
1039 struct giop_module_key module_key, *new_module_key;
1040 struct giop_module_val *module_val = NULL;
1042 module_key.module = module; /* module name */
1044 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1047 return; /* module name collision */
1050 /* So, passed module name should NOT exist in hash at this point.*/
1053 printf("giop:register_module: Adding Module %s to module hash \n", module);
1054 printf("giop:register_module: Module sub dissector name is %s \n", name);
1057 new_module_key = g_mem_chunk_alloc(giop_module_keys);
1058 new_module_key->module = module; /* save Module or interface name from IDL */
1060 module_val = g_mem_chunk_alloc(giop_module_vals);
1062 module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
1064 module_val->subh->sub_name = name; /* save dissector name */
1065 module_val->subh->sub_fn = sub; /* save subdissector*/
1066 module_val->subh->sub_proto = sub_proto; /* save subdissector's proto_XXX value */
1068 g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1075 /* Object Key Hash "EQUAL" Functions */
1077 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1078 struct giop_object_key *v1 = (struct giop_object_key *)v;
1079 struct giop_object_key *v2 = (struct giop_object_key *)w;
1081 if (v1->objkey_len != v2->objkey_len)
1082 return 0; /* no match because different length */
1084 /* Now do a byte comaprison */
1086 if (!memcmp(v1->objkey,v2->objkey, v1->objkey_len)) {
1087 return 1; /* compares ok */
1091 printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1094 return 0; /* found differences */
1097 /* Object Key Hash "HASH" Functions */
1099 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1100 struct giop_object_key *key = (struct giop_object_key *)v;
1103 guint32 val = 0; /* init hash value */
1107 * Hmm, try this simple hashing scheme for now.
1108 * ie: Simple summation
1114 printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1117 for (i=0; i< key->objkey_len; i++) {
1118 val += (guint8) key->objkey[i];
1126 * Routine to take an object key octet sequence, and length, and ptr to
1127 * a (null terminated )repository ID string, and store them in the obect key hash.
1129 * Blindly Inserts even if it does exist, See TODO at top for reason.
1132 static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
1134 struct giop_object_key objkey_key, *new_objkey_key;
1135 struct giop_object_val *objkey_val = NULL;
1137 objkey_key.objkey_len = len; /* length */
1138 objkey_key.objkey = obj; /* object key octet sequence */
1140 /* Look it up to see if it exists */
1142 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1144 /* CHANGED -- Same reqid, so abandon old entry */
1147 g_hash_table_remove(hash, &objkey_key);
1150 /* So, passed key should NOT exist in hash at this point.*/
1152 new_objkey_key = g_mem_chunk_alloc(giop_objkey_keys);
1153 new_objkey_key->objkey_len = len; /* save it */
1154 new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */
1156 objkey_val = g_mem_chunk_alloc(giop_objkey_vals);
1157 objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
1158 objkey_val->src = src; /* where IOR came from */
1162 printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
1163 objkey_val->repo_id, new_objkey_key->objkey_len);
1166 g_hash_table_insert(hash, new_objkey_key, objkey_val);
1173 * convert an ascii char representing a hex value,
1174 * to a numeric value.
1176 * returns value, or -1 if problem.
1180 static gint8 hex_char_to_val(guchar c){
1187 retval = c - 48; /* convert digit */
1191 c = toupper(c); /* convert to uppercase */
1192 if (c >= 'A' && c <= 'F') {
1203 * Convert from stringified IOR of the kind IOR:af4f7e459f....
1204 * to an IOR octet sequence.
1206 * User must free buffer.
1208 * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1209 * grab repoid etc for our objkey hash.
1213 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1216 gint8 tmpval; /* complete value */
1219 *out = g_new0(guint8, in_len); /* allocate buffer */
1225 /* skip past IOR: and convert character pairs to guint8 */
1227 for (i=4; i<in_len-1; i+=2) {
1228 if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1230 if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1231 g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1235 if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1236 g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1239 tmpval = tmpval_msb << 4;
1240 tmpval += tmpval_lsb;
1241 (*out)[(i-4)/2] = (guint8) tmpval;
1251 return (i-4)/2; /* length */
1258 * Simple getline, copied from somewhere :)
1262 static int getline(FILE *fp, gchar *line, int maxlen) {
1264 if (fgets(line,maxlen,fp) == NULL)
1267 return strlen(line);
1273 * Read a list of stringified IOR's from a named file, convert to IOR's
1274 * and store in object key hash
1277 static void read_IOR_strings_from_file(gchar *name, int max_iorlen) {
1278 guchar *buf; /* NOTE reused for every line */
1280 int ior_val_len; /* length after unstringifying. */
1282 guint8 *out; /* ptr to unstringified IOR */
1283 tvbuff_t *tvb; /* temp tvbuff for dissectin IORs */
1284 guint32 my_offset = 0;
1285 gboolean stream_is_big_endian;
1288 fp = fopen(name,"r"); /* open read only */
1291 if (errno == EACCES)
1292 fprintf(stderr, "Error opening file IOR.txt for reading: %s\n",strerror(errno));
1296 buf = g_malloc0(max_iorlen+1); /* input buf */
1298 while ((len = getline(fp,buf,max_iorlen+1)) > 0) {
1299 my_offset = 0; /* reset for every IOR read */
1301 ior_val_len = string_to_IOR(buf,len,&out); /* convert */
1305 /* Combination of tvb_new() and tvb_set_real_data().
1306 Can throw ReportedBoundsError.
1308 XXX - can it throw an exception in this case? If so, we
1309 need to catch it and clean up, but we really shouldn't allow
1310 it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
1313 tvb = tvb_new_real_data(out,ior_val_len,ior_val_len, "GIOP FILE IOR");
1315 stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1316 decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1326 fclose(fp); /* be nice */
1334 * Init routine, setup our request hash stuff, or delete old ref's
1336 * Cannot setup the module hash here as my init() may not be called before
1337 * users start registering. So I will move the module_hash stuff to
1338 * proto_register_giop, as is done with packet-rpc
1342 * Also, setup our objectkey/repoid hash here.
1346 static void giop_init(void) {
1350 * Create objkey/repoid hash, use my "equal" and "hash" functions.
1354 if (giop_objkey_hash)
1355 g_hash_table_destroy(giop_objkey_hash);
1356 if (giop_objkey_keys)
1357 g_mem_chunk_destroy(giop_objkey_keys);
1358 if (giop_objkey_vals)
1359 g_mem_chunk_destroy(giop_objkey_vals);
1363 * Create hash, use my "equal" and "hash" functions.
1367 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1369 giop_objkey_keys = g_mem_chunk_new("giop_objkey_keys",
1370 sizeof(struct giop_object_key),
1371 giop_objkey_init_count * sizeof(struct giop_object_key),
1374 giop_objkey_vals = g_mem_chunk_new("giop_objkey_vals",
1375 sizeof(struct giop_object_val),
1376 giop_objkey_init_count * sizeof(struct giop_object_val),
1381 * Create complete_reply_hash, use my "equal" and "hash" functions.
1385 if (giop_complete_reply_hash)
1386 g_hash_table_destroy(giop_complete_reply_hash);
1387 if (giop_complete_reply_keys)
1388 g_mem_chunk_destroy(giop_complete_reply_keys);
1389 if (giop_complete_reply_vals)
1390 g_mem_chunk_destroy(giop_complete_reply_vals);
1394 * Create hash, use my "equal" and "hash" functions.
1398 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1400 giop_complete_reply_keys = g_mem_chunk_new("giop_complete_reply_keys",
1401 sizeof(struct complete_reply_hash_key),
1402 complete_reply_hash_count * sizeof(struct complete_reply_hash_key),
1405 giop_complete_reply_vals = g_mem_chunk_new("giop_complete_reply_vals",
1406 sizeof(struct complete_reply_hash_val),
1407 complete_reply_hash_count * sizeof(struct complete_reply_hash_val),
1412 read_IOR_strings_from_file("IOR.txt", 600); /* testing */
1419 * Insert an entry in the GIOP Heuristic User table.
1421 * Uses giop_sub_handle_t to wrap giop user info.
1425 void register_giop_user(giop_sub_dissector_t *sub, gchar *name, int sub_proto) {
1427 giop_sub_handle_t *subh;
1429 subh = g_malloc(sizeof (giop_sub_handle_t));
1431 subh->sub_name = name;
1433 subh->sub_proto = sub_proto; /* proto_XXX from sub dissectors's proto_register_protocol() */
1435 giop_sub_list = g_slist_append (giop_sub_list, subh);
1441 * Lookup an object key in our object key hash, and return the corresponding
1446 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1448 struct giop_object_key objkey_key;
1449 struct giop_object_val *objkey_val = NULL;
1451 objkey_key.objkey_len = len; /* length */
1452 objkey_key.objkey = obj; /* object key octet sequence */
1454 /* Look it up to see if it exists */
1456 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1460 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1462 return objkey_val->repo_id; /* found */
1466 printf("FAILED Lookup of object key \n" );
1469 return NULL; /* not found */
1475 * Extract top level module/interface from repoid
1477 * eg from - "IDL:Echo/interface1:1.0"
1480 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1481 * get linux.org/Penguin/Teeth
1484 * User must free returned ptr after use.
1486 * TODO -- generalize for other Repoid encodings
1489 static gchar * get_modname_from_repoid(gchar *repoid) {
1491 gchar *modname = NULL;
1492 gchar *saved_repoid = NULL;
1494 guint8 stop_mod; /* Index of last character of modname in Repoid */
1495 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1498 saved_repoid = g_strdup(repoid); /* make a copy */
1500 /* Must start with IDL: , otherwise I get confused */
1502 if (g_strncasecmp("IDL:",repoid,4))
1505 /* Looks like a RepoID to me, so get Module or interface name */
1507 /* TODO -- put some code here to get Module name */
1509 for(i=4; c != '\0'; i++) {
1511 stop_mod = i; /* save */
1512 if (c == ':' ) /* delimiters */
1517 /* Now create a new string based on start and stop and \0 */
1519 modname = g_strndup(repoid+4, stop_mod - start_mod);
1534 * Display a "module" hash entry
1537 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1539 struct giop_module_val *mv = (struct giop_module_val *) val;
1540 struct giop_module_key *mk = (struct giop_module_key *) key;
1542 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1549 * Display a "complete_reply " hash entry
1552 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1554 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1555 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1557 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1565 * Display an "objkey" hash entry
1568 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1570 struct giop_object_val *mv = (struct giop_object_val *) val;
1571 struct giop_object_key *mk = (struct giop_object_key *) key;
1574 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1576 for (i=0; i<mk->objkey_len; i++) {
1577 printf("%.2x ", mk->objkey[i]);
1581 * If read from file, mark it as such..
1585 printf(", Repo ID = %s \n", mv->repo_id);
1588 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1596 * Display all giop_sub_list (GSList) entries
1599 static void display_heuristic_user_list() {
1602 giop_sub_handle_t *subh; /* handle */
1604 /* Get length of list */
1605 len = g_slist_length(giop_sub_list); /* find length */
1610 for (i=0; i<len; i++) {
1611 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1612 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1618 * Display all complete_request_list (GList) entries
1621 static void display_complete_request_list() {
1624 comp_req_list_entry_t *entry;
1626 /* Get length of list */
1627 len = g_list_length(giop_complete_request_list); /* find length */
1632 for (i=0; i<len; i++) {
1633 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1634 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1635 entry->reqid,entry->operation, entry->repoid);
1643 /* Dump Hash/List contents
1645 * collection_type specifies the list or hash to dump
1649 static void giop_dump_collection(collection_data_t collection_type) {
1651 switch(collection_type) {
1652 case cd_heuristic_users:
1653 printf("+----------------------------------------------+ \n");
1654 printf("+-------------- Heuristic User (Begin) --------+ \n");
1655 printf("+----------------------------------------------+ \n");
1657 display_heuristic_user_list();
1659 printf("+----------------------------------------------+ \n");
1660 printf("+-------------- Heuristic User (End) ----------+ \n");
1661 printf("+----------------------------------------------+ \n");
1665 case cd_complete_request_list:
1666 printf("+----------------------------------------------+ \n");
1667 printf("+------------- Complete Request List (Begin) --+ \n");
1668 printf("+----------------------------------------------+ \n");
1670 display_complete_request_list();
1672 printf("+----------------------------------------------+ \n");
1673 printf("+------------ Complete Request List (End) -----+ \n");
1674 printf("+----------------------------------------------+ \n");
1678 case cd_module_hash:
1679 printf("+----------------------------------------------+ \n");
1680 printf("+-------------- Module (Begin) ----------------+ \n");
1681 printf("+----------------------------------------------+ \n");
1683 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1685 printf("+----------------------------------------------+ \n");
1686 printf("+-------------- Module ( End) -----------------+ \n");
1687 printf("+----------------------------------------------+ \n\n");
1691 case cd_objkey_hash:
1692 printf("+----------------------------------------------+ \n");
1693 printf("+-------------- Objkey (Begin) ----------------+ \n");
1694 printf("+----------------------------------------------+ \n");
1696 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1698 printf("+----------------------------------------------+ \n");
1699 printf("+-------------- Objkey (End) ------------------+ \n");
1700 printf("+----------------------------------------------+ \n\n");
1704 case cd_complete_reply_hash:
1705 printf("+----------------------------------------------+ \n");
1706 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1707 printf("+----------------------------------------------+ \n");
1709 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1711 printf("+----------------------------------------------+ \n");
1712 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1713 printf("+----------------------------------------------+ \n");
1719 printf("giop: giop_dump_collection: Unknown type \n");
1730 * Loop through all subdissectors, and call them until someone
1731 * answers (returns TRUE). This function then returns TRUE, otherwise
1734 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1737 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1738 MessageHeader *header, gchar *operation ) {
1741 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1742 giop_sub_handle_t *subh = NULL;
1744 len = g_slist_length(giop_sub_list); /* find length */
1749 for (i=0; i<len; i++) {
1750 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1752 if (proto_is_protocol_enabled(subh->sub_proto)) {
1753 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1755 return TRUE; /* found one, lets return */
1757 } /* protocol_is_enabled */
1760 return res; /* result */
1766 * Find the matching repoid in the module hash and call
1767 * the dissector function if offset exists.
1770 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1771 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1777 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1778 MessageHeader *header, gchar *operation, gchar *repoid ) {
1780 giop_sub_handle_t *subdiss = NULL; /* handle */
1781 gboolean res = FALSE;
1782 gchar *modname = NULL;
1783 struct giop_module_key module_key;
1784 struct giop_module_val *module_val = NULL;
1788 * Get top level module/interface from complete repoid
1791 modname = get_modname_from_repoid(repoid);
1792 if (modname == NULL) {
1793 return res; /* unknown module name */
1797 /* Search for Module or interface name */
1799 module_key.module = modname; /* module name */
1800 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1802 if (module_val == NULL) {
1803 return res; /* module not registered */
1806 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1809 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1810 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1811 /* but only if user not clicking */
1813 if (!pinfo->fd->flags.visited)
1814 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1817 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1819 if (tvb_offset_exists(tvb, *offset)) {
1821 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1824 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1826 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1828 } /* protocol_is_enabled */
1829 } /* offset exists */
1832 return res; /* return result */
1837 /* Take in an array of char and create a new string.
1838 * Replace non-printable characters with periods.
1840 * The array may contain \0's so dont use strdup
1841 * The string is \0 terminated, and thus longer than
1842 * the initial sequence.
1843 * Caller must free the new string.
1846 static gchar * make_printable_string (gchar *in, guint32 len) {
1848 gchar *print_string = NULL;
1850 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1851 memcpy(print_string, in, len); /* and make a copy of input data */
1853 for(i=0; i < len; i++) {
1854 if( !isprint( (unsigned char)print_string[i] ) )
1855 print_string[i] = '.';
1858 return print_string; /* return ptr */
1861 /* Determine the byte order from the GIOP MessageHeader */
1863 gboolean is_big_endian (MessageHeader * header) {
1864 gboolean big_endian = FALSE;
1866 switch (header->GIOP_version.minor) {
1869 if (header->flags & 0x01)
1889 * Calculate new offset, based on the current offset, and user supplied
1890 * "offset delta" value, and the alignment requirement.
1894 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1895 * aligned on 8 byte boundaries.
1898 static void set_new_alignment(int *offset, int delta, int alignment) {
1900 while( ( (*offset + delta) % alignment) != 0)
1909 * ------------------------------------------------------------------------------------------+
1910 * Public get_CDR_xxx functions.
1911 * ------------------------------------------------------------------------------------------+
1917 * Gets data of type any. This is encoded as a TypeCode
1918 * followed by the encoded value.
1921 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1922 gboolean stream_is_big_endian, int boundary,
1923 MessageHeader * header ) {
1925 guint32 TCKind; /* TypeCode */
1927 /* get TypeCode of any */
1928 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1930 /* dissect data of type TCKind */
1931 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1935 /* Copy a 1 octet sequence from the tvbuff
1936 * which represents a boolean value, and convert
1937 * it to a boolean value.
1938 * Offset is then incremented by 1, to indicate the 1 octet which
1939 * has been processed.
1942 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1945 val = tvb_get_guint8(tvb, *offset); /* easy */
1950 /* Copy a 1 octet sequence from the tvbuff
1951 * which represents a char, and convert
1952 * it to an char value.
1953 * offset is then incremented by 1, to indicate the 1 octet which
1954 * has been processed.
1957 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1960 val = tvb_get_guint8(tvb, *offset); /* easy */
1968 * Floating Point Data Type double IEEE 754-1985
1970 * Copy an 8 octet sequence from the tvbuff
1971 * which represents a double value, and convert
1972 * it to a double value, taking into account byte order.
1973 * offset is first incremented so that it falls on a proper alignment
1974 * boundary for double values.
1975 * offset is then incremented by 8, to indicate the 8 octets which
1976 * have been processed.
1979 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1982 guint8 e1,e2,f1,f2,f3,f4,f5,f6,f7;
1985 guint32 fract0, fract1;
1989 /* double values must be aligned on a 8 byte boundary */
1991 while( ( (*offset + boundary) % 8) != 0)
1995 if(stream_is_big_endian) {
1996 e1 = get_CDR_octet(tvb,offset);
1997 sign = e1 >> 7; /* sign value */
1998 e1 &= 0x7f; /* bottom 7 bits */
1999 f1 = get_CDR_octet(tvb,offset);
2001 f1 &= 0x0f; /* bottom 4 bits */
2002 f2 = get_CDR_octet(tvb,offset);
2003 f3 = get_CDR_octet(tvb,offset);
2004 f4 = get_CDR_octet(tvb,offset);
2005 f5 = get_CDR_octet(tvb,offset);
2006 f6 = get_CDR_octet(tvb,offset);
2007 f7 = get_CDR_octet(tvb,offset);
2011 f7 = get_CDR_octet(tvb,offset);
2012 f6 = get_CDR_octet(tvb,offset);
2013 f5 = get_CDR_octet(tvb,offset);
2014 f4 = get_CDR_octet(tvb,offset);
2015 f3 = get_CDR_octet(tvb,offset);
2016 f2 = get_CDR_octet(tvb,offset);
2017 f1 = get_CDR_octet(tvb,offset);
2019 f1 &= 0x0f; /* bottom 4 bits */
2020 e1 = get_CDR_octet(tvb,offset);
2021 sign = e1 >> 7; /* sign value */
2022 e1 &= 0x7f; /* bottom 7 bits */
2026 exp = (e1 << 4) + e2;
2028 /* Now lets do some 52 bit math with 32 bit constraint */
2030 fract0 = f7 + (f6 << 8) + (f5 << 16) + (f4 << 24); /* lower 32 bits of fractional part */
2031 fract1 = f3 + (f2 << 8) + (f1 << 16); /* top 20 bits of fractional part */
2033 d_fract = (fract1 / (pow(2,20))) + (fract0 / (pow(2,52))); /* 52 bits represent a fraction */
2035 val = pow(-1,sign) * pow(2,(exp - 1023)) * (1 + d_fract);
2037 return val; /* FIX rounding ?? */
2042 /* Copy a 4 octet sequence from the tvbuff
2043 * which represents an enum value, and convert
2044 * it to an enum value, taking into account byte order.
2045 * offset is first incremented so that it falls on a proper alignment
2046 * boundary for an enum (4)
2047 * offset is then incremented by 4, to indicate the 4 octets which
2048 * have been processed.
2050 * Enum values are encoded as unsigned long.
2054 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2056 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2062 * Copy an octet sequence from the tvbuff
2063 * which represents a Fixed point decimal type, and create a string representing
2064 * a Fixed point decimal type. There are no alignment restrictions.
2065 * Size and scale of fixed decimal type is determined by IDL.
2067 * digits - IDL specified number of "digits" for this fixed type
2068 * scale - IDL specified "scale" for this fixed type
2071 * eg: typedef fixed <5,2> fixed_t;
2072 * could represent numbers like 123.45, 789.12,
2075 * As the fixed type could be any size, I will not try to fit it into our
2076 * simple types like gdouble or glong etc. I will just create a string buffer holding
2077 * a representation (after scale is applied), and with a decimal point or zero padding
2078 * inserted at the right place if necessary. The string is null terminated
2080 * so string may look like
2083 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2085 * According to spec, digits <= 31
2086 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2089 * User must remember to free the buffer
2094 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2096 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2097 guint32 i ; /* loop */
2098 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2099 /* this does not include sign, decimal point and \0 */
2100 guint32 sindex = 0; /* string index */
2101 gchar *tmpbuf; /* temp buff, holds string without scaling */
2102 guint8 tval; /* temp val storage */
2105 * how many bytes to hold digits and scale (if scale <0)
2107 * eg: fixed <5,2> = 5 digits
2108 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2112 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2116 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2118 slen = digits; /* digits */
2122 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2125 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2128 * Register a cleanup function in case on of our tvbuff accesses
2129 * throws an exception. We need to clean up tmpbuf.
2131 CLEANUP_PUSH(g_free, tmpbuf);
2133 /* If even , grab 1st dig */
2135 if (!(digits & 0x01)) {
2136 tval = get_CDR_octet(tvb,offset);
2138 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2140 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2145 * Loop, but stop BEFORE we hit last digit and sign
2146 * if digits = 1 or 2, then this part is skipped
2150 for(i=0; i< ((digits-1)/2 ); i++) {
2151 tval = get_CDR_octet(tvb,offset);
2153 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2156 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2158 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2165 printf("giop:get_CDR_fixed(): before last digit \n");
2169 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2171 tval = get_CDR_octet(tvb,offset);
2173 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2175 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2178 sign = tval & 0x0f; /* get sign */
2180 /* So now, we have all digits in an array, and the sign byte
2181 * so lets generate a printable string, taking into account the scale
2185 sindex = 0; /* reset */
2186 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2187 * \0 -- TODO check slen is reasonable first */
2189 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2194 (*seq)[sindex] = '+'; /* put sign in first string position */
2197 (*seq)[sindex] = '-';
2200 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2201 (*seq)[sindex] = '*'; /* flag as sign unkown */
2207 /* Add decimal point or padding 0's, depending if scale is positive or
2208 * negative, respectively
2212 for (i=0; i<digits-scale; i++) {
2213 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2217 (*seq)[sindex] = '.'; /* decimal point */
2220 for (i=digits-scale; i<digits; i++) {
2221 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2225 (*seq)[sindex] = '\0'; /* string terminator */
2229 /* negative scale, dump digits and pad out with 0's */
2231 for (i=0; i<digits-scale; i++) {
2233 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2235 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2240 (*seq)[sindex] = '\0'; /* string terminator */
2245 * We're done with tmpbuf, so we can call the cleanup handler to free
2246 * it, and then pop the cleanup handler.
2248 CLEANUP_CALL_AND_POP;
2251 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2261 * Floating Point Data Type float IEEE 754-1985
2263 * Copy an 4 octet sequence from the tvbuff
2264 * which represents a float value, and convert
2265 * it to a float value, taking into account byte order.
2266 * offset is first incremented so that it falls on a proper alignment
2267 * boundary for float values.
2268 * offset is then incremented by 4, to indicate the 4 octets which
2269 * have been processed.
2272 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2275 guint8 e1,e2,f1,f2,f3;
2281 /* float values must be aligned on a 4 byte boundary */
2283 while( ( (*offset + boundary) % 4) != 0)
2286 if(stream_is_big_endian) {
2287 e1 = get_CDR_octet(tvb,offset);
2288 sign = e1 >> 7; /* sign value */
2289 e1 &= 0x7f; /* bottom 7 bits */
2290 f1 = get_CDR_octet(tvb,offset);
2292 f1 &= 0x7f; /* bottom 7 bits */
2293 f2 = get_CDR_octet(tvb,offset);
2294 f3 = get_CDR_octet(tvb,offset);
2298 f3 = get_CDR_octet(tvb,offset);
2299 f2 = get_CDR_octet(tvb,offset);
2300 f1 = get_CDR_octet(tvb,offset);
2302 f1 &= 0x7f; /* bottom 7 bits */
2303 e1 = get_CDR_octet(tvb,offset);
2304 sign = e1 >> 7; /* sign value */
2305 e1 &= 0x7f; /* bottom 7 bits */
2310 exp = (e1 << 1) + e2;
2311 fract = f3 + (f2 << 8) + (f1 << 16);
2313 d_fract = fract / (pow(2,23)); /* 23 bits represent a fraction */
2315 val = pow(-1,sign) * pow(2,(exp - 127)) * (1 + d_fract);
2317 return val; /* FIX rounding ?? */
2323 * Decode an Interface type, and display it on the tree.
2326 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2327 gboolean stream_is_big_endian, int boundary) {
2330 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2336 /* Copy a 4 octet sequence from the tvbuff
2337 * which represents a signed long value, and convert
2338 * it to an signed long vaule, taking into account byte order.
2339 * offset is first incremented so that it falls on a proper alignment
2340 * boundary for long values.
2341 * offset is then incremented by 4, to indicate the 4 octets which
2342 * have been processed.
2345 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2349 /* unsigned long values must be aligned on a 4 byte boundary */
2350 while( ( (*offset + boundary) % 4) != 0)
2353 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2354 tvb_get_letohl (tvb, *offset);
2361 * Decode an Object type, and display it on the tree.
2364 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2365 gboolean stream_is_big_endian, int boundary) {
2367 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2373 /* Copy a 1 octet sequence from the tvbuff
2374 * which represents a octet, and convert
2375 * it to an octet value.
2376 * offset is then incremented by 1, to indicate the 1 octet which
2377 * has been processed.
2380 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2383 val = tvb_get_guint8(tvb, *offset); /* easy */
2389 /* Copy a sequence of octets from the tvbuff.
2390 * Caller of this function must remember to free the
2391 * array pointed to by seq.
2392 * This function also increments offset by len.
2395 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, int len) {
2397 if (! tvb_bytes_exist(tvb, *offset,len)) {
2399 * Generate an exception, and stop processing.
2400 * We do that now, rather than after allocating the buffer, so we
2401 * don't have to worry about freeing the buffer.
2402 * XXX - would we be better off using a cleanup routine?
2404 tvb_get_guint8(tvb, *offset + len);
2408 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2409 * do what we do now, and null-terminate the string (which also means
2410 * we don't need to zero out the entire allocation, just the last byte)?
2412 *seq = g_new0(gchar, len + 1);
2413 tvb_memcpy( tvb, *seq, *offset, len);
2418 /* Copy a 2 octet sequence from the tvbuff
2419 * which represents a signed short value, and convert
2420 * it to a signed short value, taking into account byte order.
2421 * offset is first incremented so that it falls on a proper alignment
2422 * boundary for short values.
2423 * offset is then incremented by 2, to indicate the 2 octets which
2424 * have been processed.
2427 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2431 /* short values must be aligned on a 2 byte boundary */
2432 while( ( (*offset + boundary) % 2) != 0)
2435 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2436 tvb_get_letohs (tvb, *offset);
2444 /* Copy an octet sequence from the tvbuff
2445 * which represents a string, and convert
2446 * it to an string value, taking into account byte order.
2447 * offset is first incremented so that it falls on a proper alignment
2448 * boundary for string values. (begins with an unsigned long LI)
2450 * String sequence is copied to a buffer "seq". This must
2451 * be freed by the calling program.
2452 * offset is then incremented, to indicate the octets which
2453 * have been processed.
2455 * returns number of octets in the sequence
2457 * Note: This function only supports single byte encoding at the
2458 * moment until I get a handle on multibyte encoding etc.
2463 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2468 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2471 (*offset)++; /* must step past \0 delimiter */
2475 get_CDR_octet_seq(tvb, seq, offset, slength);
2477 *seq = g_strdup(""); /* zero-length string */
2480 return slength; /* return length */
2484 /* Process a sequence of octets that represent the
2485 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2487 * This function also increments offset to the correct position.
2489 * It will parse the TypeCode and output data to the "tree" provided
2492 * It returns a guint32 representing a TCKind value.
2495 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2496 gboolean stream_is_big_endian, int boundary,
2497 MessageHeader * header ) {
2500 gint16 s_octet2; /* signed int16 */
2501 guint16 u_octet2; /* unsigned int16 */
2502 guint32 u_octet4; /* unsigned int32 */
2504 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2506 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2507 *offset-sizeof(val),4,val);
2510 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2513 case tk_null: /* empty parameter list */
2515 case tk_void: /* empty parameter list */
2517 case tk_short: /* empty parameter list */
2519 case tk_long: /* empty parameter list */
2521 case tk_ushort: /* empty parameter list */
2523 case tk_ulong: /* empty parameter list */
2525 case tk_float: /* empty parameter list */
2527 case tk_double: /* empty parameter list */
2529 case tk_boolean: /* empty parameter list */
2531 case tk_char: /* empty parameter list */
2533 case tk_octet: /* empty parameter list */
2535 case tk_any: /* empty parameter list */
2537 case tk_TypeCode: /* empty parameter list */
2539 case tk_Principal: /* empty parameter list */
2541 case tk_objref: /* complex parameter list */
2542 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2544 case tk_struct: /* complex parameter list */
2545 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2547 case tk_union: /* complex parameter list */
2548 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2550 case tk_enum: /* complex parameter list */
2551 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2554 case tk_string: /* simple parameter list */
2555 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2557 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2558 *offset-sizeof(u_octet4),4,u_octet4);
2562 case tk_sequence: /* complex parameter list */
2563 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2565 case tk_array: /* complex parameter list */
2566 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2568 case tk_alias: /* complex parameter list */
2569 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2571 case tk_except: /* complex parameter list */
2572 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2574 case tk_longlong: /* empty parameter list */
2576 case tk_ulonglong: /* empty parameter list */
2578 case tk_longdouble: /* empty parameter list */
2580 case tk_wchar: /* empty parameter list */
2582 case tk_wstring: /* simple parameter list */
2583 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2585 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2586 *offset-sizeof(u_octet4),4,u_octet4);
2590 case tk_fixed: /* simple parameter list */
2591 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2593 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2594 *offset-sizeof(u_octet2),2,u_octet2);
2597 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2599 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2600 *offset-sizeof(s_octet2),2,s_octet2);
2604 case tk_value: /* complex parameter list */
2605 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2607 case tk_value_box: /* complex parameter list */
2608 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2610 case tk_native: /* complex parameter list */
2611 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2613 case tk_abstract_interface: /* complex parameter list */
2614 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2617 g_warning("giop: Unknown TCKind %u \n", val);
2626 /* Copy a 4 octet sequence from the tvbuff
2627 * which represents an unsigned long value, and convert
2628 * it to an unsigned long vaule, taking into account byte order.
2629 * offset is first incremented so that it falls on a proper alignment
2630 * boundary for unsigned long values.
2631 * offset is then incremented by 4, to indicate the 4 octets which
2632 * have been processed.
2635 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2639 /* unsigned long values must be aligned on a 4 byte boundary */
2640 while( ( (*offset + boundary) % 4) != 0)
2643 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2644 tvb_get_letohl (tvb, *offset);
2651 /* Copy a 2 octet sequence from the tvbuff
2652 * which represents an unsigned short value, and convert
2653 * it to an unsigned short value, taking into account byte order.
2654 * offset is first incremented so that it falls on a proper alignment
2655 * boundary for unsigned short values.
2656 * offset is then incremented by 2, to indicate the 2 octets which
2657 * have been processed.
2660 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2664 /* unsigned short values must be aligned on a 2 byte boundary */
2665 while( ( (*offset + boundary) % 2) != 0)
2668 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2669 tvb_get_letohs (tvb, *offset);
2677 /* Copy a wchar from the tvbuff.
2678 * Caller of this function must remember to free the
2679 * array pointed to by seq.
2680 * This function also increments offset according to
2683 * For GIOP 1.1 read 2 octets and return size -2. The
2684 * negation means there is no size element in the packet
2685 * and therefore no size to add to the tree.
2687 * For GIOP 1.2 read size of wchar and the size
2688 * octets. size is returned as a gint8.
2690 * For both GIOP versions the wchar is returned
2691 * as a printable string.
2695 /* NOTE: This is very primitive in that it just reads
2696 * the wchar as a series of octets and returns them
2697 * to the user. No translation is attempted based on
2698 * byte orientation, nor on code set. I.e it only
2699 * really reads past the wchar and sets the offset
2703 /* The "decoding" is done according to CORBA chapter 15.
2704 * Wchar is not supported for GIOP 1.0.
2707 gint8 get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2712 /* CORBA chapter 15:
2713 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2714 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2715 * followed by the elements of the octet sequence representing
2716 * the encoded value of the wchar.
2719 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2720 slength = 2; /* set for GIOP 1.1 length in octets */
2722 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2723 slength = get_CDR_octet(tvb,offset);
2726 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2727 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2729 /* now turn octets (wchar) into something that can be printed by the user */
2730 *seq = make_printable_string(raw_wstring, slength);
2732 g_free(raw_wstring);
2735 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2736 if (header->GIOP_version.minor < 2)
2739 return slength; /* return length */
2744 /* Copy a wstring from the tvbuff.
2745 * Caller of this function must remember to free the
2746 * array pointed to by seq.
2747 * This function also increments offset, according to
2748 * wstring length. length is returned as guint32
2751 /* NOTE: This is very primitive in that it just reads
2752 * the wstring as a series of octets and returns them
2753 * to the user. No translation is attempted based on
2754 * byte orientation, nor on code set. I.e it only
2755 * really reads past the wstring and sets the offset
2759 /* The "decoding" is done according to CORBA chapter 15.
2760 * Wstring is not supported for GIOP 1.0.
2764 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2765 int boundary, MessageHeader * header) {
2770 /* CORBA chapter 15:
2771 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2772 * length and string are NUL terminated (length???).
2773 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2777 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2779 /* get length, same for all GIOP versions,
2780 * although for 1.2 CORBA doesnt say, so assume.
2782 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2786 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2787 slength = 5; /* better than core dumping during debug */
2791 if (header->GIOP_version.minor < 2) {
2793 (*offset)++; /* must step past \0 delimiter */
2795 /* assume length is number of characters and not octets, spec not clear */
2796 slength = slength * 2; /* length in octets is 2 * wstring length */
2800 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2802 /* now turn octets (wstring) into something that can be printed by the user */
2803 *seq = make_printable_string(raw_wstring, slength);
2805 g_free(raw_wstring);
2808 return slength; /* return length */
2815 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2817 * typedef short AddressingDisposition;
2818 * const short KeyAddr = 0;
2819 * const short ProfileAddr = 1;
2820 * const short ReferenceAddr = 2;
2821 * struct IORAddressingInfo {
2822 * unsigned long selected_profile_index;
2826 * union TargetAddress switch (AddressingDisposition) {
2827 * case KeyAddr: sequence <octet> object_key;
2828 * case ProfileAddr: IOP::TaggedProfile profile;
2829 * case ReferenceAddr: IORAddressingInfo ior;
2834 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2835 MessageHeader * header, gboolean stream_is_big_endian)
2837 guint16 discriminant;
2839 gchar *p_object_key;
2843 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2846 proto_tree_add_text (tree, tvb, *offset -2, 2,
2847 "TargetAddress Discriminant: %u", discriminant);
2850 switch (discriminant)
2852 case 0: /* KeyAddr */
2853 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2856 proto_tree_add_text (tree, tvb, *offset -4, 4,
2857 "KeyAddr (object key length): %u", len);
2862 get_CDR_octet_seq(tvb, &object_key, offset, len);
2863 p_object_key = make_printable_string( object_key, len );
2867 proto_tree_add_text (tree, tvb, *offset -len, len,
2868 "KeyAddr (object key): %s", p_object_key);
2870 g_free( p_object_key );
2871 g_free( object_key );
2874 case 1: /* ProfileAddr */
2875 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2876 stream_is_big_endian, NULL);
2878 case 2: /* ReferenceAddr */
2879 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2883 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2884 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2887 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2895 dissect_reply_body (tvbuff_t *tvb, u_int offset, packet_info *pinfo,
2896 proto_tree *tree, gboolean stream_is_big_endian,
2897 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2899 u_int sequence_length;
2900 gboolean exres = FALSE; /* result of trying explicit dissectors */
2901 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2904 * comp_req_list stuff
2907 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2911 switch (reply_status)
2913 case SYSTEM_EXCEPTION:
2915 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2918 case USER_EXCEPTION:
2920 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2924 proto_tree_add_text(tree, tvb, offset-4, 4,
2925 "Exception length: %u", sequence_length);
2927 if (sequence_length != 0)
2931 proto_tree_add_text(tree, tvb, offset, sequence_length,
2933 tvb_format_text(tvb, offset, sequence_length));
2937 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2939 /* read exception id from buffer and store in*/
2941 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2947 offset += sequence_length;
2953 * Now just fall through to the NO_EXCEPTION part
2954 * as this is common .
2962 /* lookup MFN in hash directly */
2964 mfn = get_mfn_from_fn(pinfo->fd->num);
2966 if (mfn == pinfo->fd->num)
2967 return; /* no matching frame number, what am I */
2969 /* get entry for this MFN */
2970 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2973 return; /* no matching entry */
2977 * If this packet is a REPLY to a RESOLVE(request)
2979 * TODO - make this lookup faster -- FS
2982 if (!strcmp(giop_op_resolve,entry->operation)) {
2983 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2987 /* TODO -- Put stuff here for other "interesting operations" */
2991 * Call sub dissector.
2992 * First try an find a explicit sub_dissector, then if that
2993 * fails, try the heuristic method.
2998 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
3001 /* Only call heuristic if no explicit dixxector was found */
3004 try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
3010 case LOCATION_FORWARD:
3011 g_warning("giop: We don't yet dissect LOCATION_FORWARD\n");
3015 case LOCATION_FORWARD_PERM:
3016 g_warning("giop: We don't yet dissect LOCATION_FORWARD_PERM\n");
3020 case NEEDS_ADDRESSING_MODE:
3021 g_warning("giop: We don't yet dissect NEEDS_ADDRESSING_MODE\n");
3027 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
3033 g_free(repoid); /* free resource */
3043 /* The format of the Reply Header for GIOP 1.0 and 1.1
3044 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
3046 struct ReplyHeader_1_0 {
3047 IOP::ServiceContextList service_context;
3048 unsigned long request_id;
3049 ReplyStatusType_1_0 reply_status;
3053 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3054 proto_tree * clnp_tree, MessageHeader * header,
3055 gboolean stream_is_big_endian) {
3059 guint32 reply_status;
3060 proto_tree *reply_tree = NULL;
3062 guint32 mfn; /* matching frame number */
3065 tf = proto_tree_add_text (tree, tvb, offset,
3067 "General Inter-ORB Protocol Reply");
3068 if (reply_tree == NULL)
3070 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3076 * Decode IOP::ServiceContextList
3079 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3081 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3083 if (check_col(pinfo->fd, COL_INFO)) {
3084 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3088 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3089 "Request id: %u", request_id);
3092 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3094 if (check_col(pinfo->fd, COL_INFO)) {
3095 col_append_fstr(pinfo->fd, COL_INFO, ": %s",
3096 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3101 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3103 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3108 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3111 if (! pinfo->fd->flags.visited) {
3112 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3113 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3114 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3118 header->req_id = request_id; /* save for sub dissector */
3119 header->rep_status = reply_status; /* save for sub dissector */
3121 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3122 reply_status, header,tree);
3127 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3128 * and 1.1 header, only the fields have been rearranged. From Section
3129 * 15.4.3.1 of the CORBA 2.4 specification:
3131 * struct ReplyHeader_1_2 {
3132 * unsigned long request_id;
3133 * ReplyStatusType_1_2 reply_status;
3134 * IOP:ServiceContextList service_context;
3138 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3139 proto_tree * tree, proto_tree * clnp_tree,
3140 MessageHeader * header,
3141 gboolean stream_is_big_endian) {
3145 guint32 reply_status;
3146 proto_tree *reply_tree = NULL;
3148 guint32 mfn; /* matching frame number */
3151 tf = proto_tree_add_text (tree, tvb, offset,
3153 "General Inter-ORB Protocol Reply");
3154 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3157 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3159 if (check_col(pinfo->fd, COL_INFO)) {
3160 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3164 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3165 "Request id: %u", request_id);
3168 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3170 if (check_col(pinfo->fd, COL_INFO)) {
3171 col_append_fstr(pinfo->fd, COL_INFO, ": %s",
3172 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3177 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3179 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3184 * Decode IOP::ServiceContextList
3187 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3190 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3193 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3196 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3199 if (! pinfo->fd->flags.visited) {
3200 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3201 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3202 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3207 * Add header to argument list so sub dissector can get header info.
3210 header->req_id = request_id; /* save for sub dissector */
3211 header->rep_status = reply_status; /* save for sub dissector */
3213 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3214 reply_status,header,tree);
3220 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3221 proto_tree * tree, proto_tree * clnp_tree,
3222 MessageHeader * header, gboolean stream_is_big_endian) {
3226 proto_tree *cancel_request_tree = NULL;
3230 tf = proto_tree_add_text (tree, tvb, offset,
3232 "General Inter-ORB Protocol CancelRequest");
3233 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3236 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3238 if (check_col(pinfo->fd, COL_INFO)) {
3239 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3243 proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4,
3244 "Request id: %u", request_id);
3250 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3251 * in section 15.4.2.1 of the CORBA 2.4 specification.
3253 * struct RequestHeader{
3254 * IOP::ServiceContextList service_context;
3255 * unsigned long request_id;
3256 * boolean response_expected;
3257 * octet reserved[3]; // Only in GIOP 1.1
3258 * sequence<octet> object_key;
3260 * CORBA::OctetSeq requesting_principal;
3264 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3265 proto_tree * tree, proto_tree * clnp_tree,
3266 MessageHeader * header, gboolean stream_is_big_endian)
3272 guint32 objkey_len = 0; /* object key length */
3273 gchar *objkey = NULL; /* object key sequence */
3274 gchar *print_objkey; /* printable object key sequence */
3275 gboolean exres = FALSE; /* result of trying explicit dissectors */
3278 gchar *requesting_principal;
3279 gchar *print_requesting_principal;
3280 guint8 response_expected;
3282 proto_tree *request_tree = NULL;
3285 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3290 tf = proto_tree_add_text (tree, tvb, offset,
3292 "General Inter-ORB Protocol Request");
3293 if (request_tree == NULL)
3295 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3304 * Decode IOP::ServiceContextList
3307 decode_ServiceContextList(tvb, pinfo, request_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3310 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3311 if (check_col(pinfo->fd, COL_INFO))
3313 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3317 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3318 "Request id: %u", request_id);
3321 response_expected = tvb_get_guint8( tvb, offset );
3323 if (check_col(pinfo->fd, COL_INFO))
3325 col_append_fstr(pinfo->fd, COL_INFO, " (%s)",
3326 response_expected ? "two-way" : "one-way");
3330 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3331 "Response expected: %u", response_expected);
3334 if( header->GIOP_version.minor > 0)
3336 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3339 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3340 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3347 /* Length of object_key sequence */
3348 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3353 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3354 /**/ "Object Key length: %u", objkey_len);
3359 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3361 print_objkey = make_printable_string(objkey, objkey_len);
3365 proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
3366 /**/ "Object Key: %s", print_objkey);
3370 g_free( print_objkey );
3374 * Register a cleanup function in case on of our tvbuff accesses
3375 * throws an exception. We need to clean up objkey.
3377 CLEANUP_PUSH(g_free, objkey);
3379 /* length of operation string and string */
3380 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3383 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3384 /**/ "Operation length: %u", len);
3389 if (check_col(pinfo->fd, COL_INFO))
3391 col_append_fstr(pinfo->fd, COL_INFO, ": %s", operation);
3395 proto_tree_add_text (request_tree, tvb, offset - len, len,
3396 /**/ "Operation: %s", operation);
3402 * Register a cleanup function in case on of our tvbuff accesses
3403 * throws an exception. We need to clean up operation.
3405 CLEANUP_PUSH(g_free, operation);
3407 /* length of requesting_principal string */
3408 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3411 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3412 /**/ "Requesting Principal Length: %u", len);
3417 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3419 print_requesting_principal = make_printable_string(requesting_principal, len);
3423 proto_tree_add_text (request_tree, tvb, offset - len, len,
3424 /**/ "Requesting Principal: %s", print_requesting_principal);
3428 g_free( print_requesting_principal );
3429 g_free( requesting_principal );
3434 * Save FN,reqid,and operation for later. Add sub_handle later.
3435 * But only if user is NOT clicking.
3438 if (! pinfo->fd->flags.visited)
3439 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3440 request_id,operation,NULL);
3444 * Call subdissector here before freeing "operation" and "key"
3445 * pass request_id also.
3446 * First try an find an explicit sub_dissector, then if that
3447 * fails, try the heuristic method.
3452 header->req_id = request_id; /* save for sub dissector */
3453 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3457 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3460 /* Only call heuristic if no explicit dissector was found */
3463 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3468 * We're done with operation, so we can call the cleanup handler to free
3469 * it, and then pop the cleanup handler.
3471 CLEANUP_CALL_AND_POP;
3474 * We're done with objkey, so we can call the cleanup handler to free
3475 * it, and then pop the cleanup handler.
3477 CLEANUP_CALL_AND_POP;
3481 /** The format of a GIOP 1.2 RequestHeader message is
3482 * (CORBA 2.4, sec. 15.4.2):
3484 * struct RequestHeader_1_2 {
3485 * unsigned long request_id;
3486 * octet response_flags;
3487 * octet reserved[3];
3488 * TargetAddress target;
3490 * IOP::ServiceContextList service_context;
3491 * // requesting_principal not in GIOP 1.2
3495 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3496 proto_tree * tree, proto_tree * clnp_tree,
3497 MessageHeader * header, gboolean stream_is_big_endian)
3502 guint8 response_flags;
3504 gchar *operation = NULL;
3505 proto_tree *request_tree = NULL;
3507 gboolean exres = FALSE; /* result of trying explicit dissectors */
3509 gchar *repoid = NULL;
3514 tf = proto_tree_add_text (tree, tvb, offset,
3516 "General Inter-ORB Protocol Request");
3517 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3520 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3521 if (check_col(pinfo->fd, COL_INFO))
3523 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3527 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3528 "Request id: %u", request_id);
3531 response_flags = tvb_get_guint8( tvb, offset );
3535 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3536 "Response flags: %s (%u)",
3537 match_strval(response_flags, sync_scope),
3541 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3544 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3545 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3549 dissect_target_address(tvb, pinfo, &offset, request_tree, header, stream_is_big_endian);
3551 /* length of operation string */
3552 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3555 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3556 /**/ "Operation length: %u", len);
3561 if (check_col(pinfo->fd, COL_INFO))
3563 col_append_fstr(pinfo->fd, COL_INFO, ": %s", operation);
3567 proto_tree_add_text (request_tree, tvb, offset - len, len,
3568 /**/ "Operation: %s", operation);
3575 * Register a cleanup function in case on of our tvbuff accesses
3576 * throws an exception. We need to clean up operation.
3578 CLEANUP_PUSH(g_free, operation);
3581 * Decode IOP::ServiceContextList
3584 decode_ServiceContextList(tvb, pinfo, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3587 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3588 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3589 * GIOP octet stream start.
3592 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3595 * Save FN,reqid,and operation for later. Add sub_handle later.
3596 * But only if user is NOT clicking.
3599 if (! pinfo->fd->flags.visited)
3600 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3601 request_id,operation,NULL);
3605 * Call sub dissector.
3606 * First try an find a explicit sub_dissector, then if that
3607 * fails, try the heuristic method.
3612 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3615 /* Only call heuristic if no explicit dissector was found */
3618 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3623 * We're done with operation, so we can call the cleanup handler to free
3624 * it, and then pop the cleanup handler.
3626 CLEANUP_CALL_AND_POP;
3630 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3631 proto_tree * tree, MessageHeader * header,
3632 gboolean stream_is_big_endian)
3638 gchar *p_object_key;
3639 proto_tree *locate_request_tree = NULL;
3644 tf = proto_tree_add_text (tree, tvb, offset,
3646 "General Inter-ORB Locate Request");
3647 if (locate_request_tree == NULL)
3649 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3654 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3655 if (check_col(pinfo->fd, COL_INFO))
3657 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3659 if (locate_request_tree)
3661 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3662 "Request id: %u", request_id);
3665 if(header->GIOP_version.minor < 2)
3667 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3668 if (locate_request_tree)
3670 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3671 "Object Key length: %u", len);
3675 get_CDR_octet_seq(tvb, &object_key, &offset, len);
3677 p_object_key = make_printable_string(object_key, len);
3679 if(locate_request_tree)
3682 proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
3683 "Object Key: %s", p_object_key);
3686 g_free(p_object_key);
3690 else /* GIOP 1.2 and higher */
3692 dissect_target_address(tvb, pinfo, &offset, locate_request_tree, header,
3693 stream_is_big_endian);
3699 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3700 proto_tree * tree, MessageHeader * header,
3701 gboolean stream_is_big_endian)
3705 guint32 locate_status;
3708 proto_tree *locate_reply_tree = NULL;
3713 tf = proto_tree_add_text (tree, tvb, offset,
3715 "General Inter-ORB Locate Reply");
3716 if (locate_reply_tree == NULL)
3718 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3723 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3724 if (check_col(pinfo->fd, COL_INFO))
3726 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3728 if (locate_reply_tree)
3730 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3731 "Request id: %u", request_id);
3734 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3735 if (locate_reply_tree)
3737 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3738 "Locate status: %s",
3739 match_strval(locate_status, giop_locate_status_types)
3743 /* Decode the LocateReply body.
3745 * For GIOP 1.0 and 1.1 body immediately follows header.
3746 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3750 if (header->GIOP_version.minor > 1) {
3751 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3755 switch(locate_status) {
3756 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3757 case OBJECT_FORWARD_PERM:
3758 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3760 case LOC_SYSTEM_EXCEPTION:
3761 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3763 case LOC_NEEDS_ADDRESSING_MODE:
3764 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3765 if(locate_reply_tree) {
3766 proto_tree_add_text (tree, tvb, offset -2, 2,
3767 "AddressingDisposition: %u", addr_disp);
3770 default: /* others have no reply body */
3777 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3778 MessageHeader * header, gboolean stream_is_big_endian)
3782 proto_tree *fragment_tree = NULL;
3787 tf = proto_tree_add_text (tree, tvb, offset,
3789 "General Inter-ORB Fragment");
3790 if (fragment_tree == NULL)
3792 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3797 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3798 if (check_col(pinfo->fd, COL_INFO))
3800 col_append_fstr(pinfo->fd, COL_INFO, " %u", request_id);
3804 proto_tree_add_text (fragment_tree, tvb, offset-4, 4,
3805 "Request id: %u", request_id);
3811 /* Main entry point */
3813 gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3815 MessageHeader header;
3816 tvbuff_t *giop_header_tvb;
3817 tvbuff_t *payload_tvb;
3819 proto_tree *clnp_tree = NULL;
3822 u_int minor_version;
3823 gboolean stream_is_big_endian;
3829 giop_dump_collection(cd_module_hash);
3830 giop_dump_collection(cd_objkey_hash);
3831 giop_dump_collection(cd_heuristic_users);
3832 giop_dump_collection(cd_complete_reply_hash);
3833 giop_dump_collection(cd_complete_request_list);
3836 header.exception_id = NULL;
3838 /* check magic number and version */
3841 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
3843 if (tvb_length_remaining(tvb, 0) < GIOP_HEADER_SIZE)
3845 /* Not enough data captured to hold the GIOP header; don't try
3846 to interpret it as GIOP. */
3850 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3851 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3854 * because I have added extra elements in MessageHeader struct
3855 * for sub dissectors. -- FS
3858 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3860 if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
3862 /* Not a GIOP message. */
3867 if (check_col (pinfo->fd, COL_PROTOCOL))
3869 col_set_str (pinfo->fd, COL_PROTOCOL, "GIOP");
3872 if (header.GIOP_version.major != GIOP_MAJOR ||
3873 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3875 /* Bad version number; should we note that and dissect the rest
3876 as data, or should we return FALSE on the theory that it
3877 might have been some other packet that happened to begin with
3878 "GIOP"? We shouldn't do *both*, so we return TRUE, for now.
3879 If we should return FALSE, we should do so *without* setting
3880 the "Info" column, *without* setting the "Protocol" column,
3881 and *without* adding anything to the protocol tree. */
3883 if (check_col (pinfo->fd, COL_INFO))
3885 col_add_fstr (pinfo->fd, COL_INFO, "Version %u.%u",
3886 header.GIOP_version.major, header.GIOP_version.minor);
3890 ti = proto_tree_add_item (tree, proto_giop, tvb, 0,
3891 tvb_length (tvb), FALSE);
3892 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3893 proto_tree_add_text (clnp_tree, giop_header_tvb, 0,
3894 tvb_length (giop_header_tvb),
3895 "Version %u.%u not supported",
3896 header.GIOP_version.major,
3897 header.GIOP_version.minor);
3899 dissect_data (payload_tvb, 0, pinfo, tree);
3903 if (check_col (pinfo->fd, COL_INFO))
3905 col_add_fstr (pinfo->fd, COL_INFO, "GIOP %u.%u %s",
3906 header.GIOP_version.major, header.GIOP_version.minor,
3907 val_to_str(header.message_type, giop_message_types,
3908 "Unknown message type (0x%02x)"));
3911 stream_is_big_endian = is_big_endian (&header);
3913 if (stream_is_big_endian)
3914 message_size = pntohl (&header.message_size);
3916 message_size = pletohl (&header.message_size);
3920 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, 12, FALSE);
3921 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3922 proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3923 "Magic number: %s", GIOP_MAGIC);
3924 proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3926 header.GIOP_version.major,
3927 header.GIOP_version.minor);
3928 switch (minor_version)
3932 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3933 "Flags: 0x%02x (%s %s)",
3935 (stream_is_big_endian) ? "big-endian" : "little-endian",
3936 (header.flags & 0x02) ? " fragment" : "");
3939 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3940 "Byte ordering: %s-endian",
3941 (stream_is_big_endian) ? "big" : "little");
3945 } /* minor_version */
3947 proto_tree_add_uint_format (clnp_tree,
3948 hf_giop_message_type,
3949 giop_header_tvb, 7, 1,
3950 header.message_type,
3951 "Message type: %s", match_strval(header.message_type, giop_message_types));
3953 proto_tree_add_uint (clnp_tree,
3954 hf_giop_message_size,
3955 giop_header_tvb, 8, 4, message_size);
3960 if (check_col (pinfo->fd, COL_INFO))
3962 col_add_fstr (pinfo->fd, COL_INFO, "GIOP %u.%u %s",
3963 header.GIOP_version.major, header.GIOP_version.minor,
3964 match_strval(header.message_type, giop_message_types));
3968 switch (header.message_type)
3972 if(header.GIOP_version.minor < 2)
3974 dissect_giop_request_1_1 (payload_tvb, pinfo, tree, clnp_tree,
3975 &header, stream_is_big_endian);
3979 dissect_giop_request_1_2 (payload_tvb, pinfo, tree, clnp_tree,
3980 &header, stream_is_big_endian);
3987 if(header.GIOP_version.minor < 2)
3989 dissect_giop_reply (payload_tvb, pinfo, tree, clnp_tree, &header,
3990 stream_is_big_endian);
3994 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree, clnp_tree,
3995 &header, stream_is_big_endian);
3999 dissect_giop_cancel_request(payload_tvb, pinfo, tree, clnp_tree,
4000 &header, stream_is_big_endian);
4003 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
4004 stream_is_big_endian);
4007 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
4008 stream_is_big_endian);
4011 dissect_giop_fragment(payload_tvb, pinfo, tree, &header,
4012 stream_is_big_endian);
4017 } /* switch message_type */
4021 * XXX - we should catch exceptions here, so that we can free
4022 * this if an exception is thrown.
4023 * We'd then have to forward the exception.
4025 if (header.exception_id != NULL)
4026 g_free(header.exception_id);
4032 proto_register_giop (void)
4034 static hf_register_info hf[] = {
4035 { &hf_giop_message_type,
4036 { "Message type", "giop.type",
4037 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4040 { &hf_giop_message_size,
4041 { "Message size", "giop.len",
4042 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4046 { "Repository ID", "giop.repoid",
4047 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4050 { &hf_giop_string_length,
4051 { "String Length", "giop.strlen",
4052 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4055 { &hf_giop_sequence_length,
4056 { "Sequence Length", "giop.seqlen",
4057 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4060 { &hf_giop_profile_id,
4061 { "Profile ID", "giop.profid",
4062 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
4067 { "IOR::type_id", "giop.typeid",
4068 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4071 { &hf_giop_iiop_v_maj,
4072 { "IIOP Major Version", "giop.iiop_vmaj",
4073 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4076 { &hf_giop_iiop_v_min,
4077 { "IIOP Minor Version", "giop.iiop_vmin",
4078 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4081 { &hf_giop_endianess,
4082 { "Endianess", "giop.endianess",
4083 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4086 { &hf_giop_IIOP_tag,
4087 { "IIOP Component TAG", "giop.iioptag",
4088 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4092 { "IOR Profile TAG", "giop.iortag",
4093 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4097 { "TypeCode enum", "giop.TCKind",
4098 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4101 { &hf_giop_typecode_count,
4102 { "TypeCode count", "giop.tccount",
4103 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4106 { &hf_giop_typecode_default_used,
4107 { "default_used", "giop.tcdefault_used",
4108 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4111 { &hf_giop_typecode_digits,
4112 { "Digits", "giop.tcdigits",
4113 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4117 { &hf_giop_typecode_length,
4118 { "Length", "giop.tclength",
4119 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4122 { &hf_giop_typecode_max_length,
4123 { "Maximum length", "giop.tcmaxlen",
4124 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4127 { &hf_giop_typecode_member_name,
4128 { "TypeCode member name", "giop.tcmemname",
4129 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4132 { &hf_giop_typecode_name,
4133 { "TypeCode name", "giop.tcname",
4134 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4137 { &hf_giop_typecode_scale,
4138 { "Scale", "giop.tcscale",
4139 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4142 { &hf_giop_typecode_ValueModifier,
4143 { "ValueModifier", "giop.tcValueModifier",
4144 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4147 { &hf_giop_typecode_Visibility,
4148 { "Visibility", "giop.tcVisibility",
4149 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4154 { &hf_giop_type_boolean,
4155 { "TypeCode boolean data", "giop.tcboolean",
4156 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4159 { &hf_giop_type_char,
4160 { "TypeCode char data", "giop.tcchar",
4161 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4164 { &hf_giop_type_double,
4165 { "TypeCode double data", "giop.tcdouble",
4166 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4169 { &hf_giop_type_enum,
4170 { "TypeCode enum data", "giop.tcenumdata",
4171 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4175 * float as double ?? -- FIX
4178 { &hf_giop_type_float,
4179 { "TypeCode float data", "giop.tcfloat",
4180 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4183 { &hf_giop_type_long,
4184 { "TypeCode long data", "giop.tclongdata",
4185 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4188 { &hf_giop_type_octet,
4189 { "TypeCode octet data", "giop.tcoctet",
4190 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4193 { &hf_giop_type_short,
4194 { "TypeCode short data", "giop.tcshortdata",
4195 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4198 { &hf_giop_type_string,
4199 { "TypeCode string data", "giop.tcstring",
4200 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4203 { &hf_giop_type_ulong,
4204 { "TypeCode ulong data", "giop.tculongdata",
4205 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4208 { &hf_giop_type_ushort,
4209 { "TypeCode ushort data", "giop.tcushortdata",
4210 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4214 * IIOP Module - Chapter 15.10.2
4217 { &hf_giop_iiop_host,
4218 { "IIOP::Profile_host", "giop.iiop.host",
4219 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4223 { &hf_giop_iiop_port,
4224 { "IIOP::Profile_port", "giop.iiop.port",
4225 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4230 * IIOP ServiceContext
4233 { &hf_giop_iop_vscid,
4234 { "VSCID", "giop.iiop.vscid",
4235 FT_UINT32, BASE_HEX, NULL, 0xfffff000, "", HFILL }
4239 { &hf_giop_iop_scid,
4240 { "SCID", "giop.iiop.scid",
4241 FT_UINT32, BASE_HEX, NULL, 0x00000fff, "", HFILL }
4248 static gint *ett[] = {
4252 &ett_giop_cancel_request,
4253 &ett_giop_locate_request,
4254 &ett_giop_locate_reply,
4260 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4262 proto_register_field_array (proto_giop, hf, array_length (hf));
4263 proto_register_subtree_array (ett, array_length (ett));
4266 /* register init routine */
4268 register_init_routine( &giop_init); /* any init stuff */
4271 * Init the giop user module hash tables here, as giop users
4272 * will populate it via register_giop_user_module BEFORE my
4273 * own giop_init() is called.
4276 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4278 giop_module_keys = g_mem_chunk_new("giop_module_keys",
4279 sizeof(struct giop_module_key),
4280 giop_module_init_count * sizeof(struct giop_module_key),
4283 giop_module_vals = g_mem_chunk_new("giop_module_vals",
4284 sizeof(struct giop_module_val),
4285 giop_module_init_count * sizeof(struct giop_module_val),
4292 void proto_reg_handoff_giop (void) {
4293 heur_dissector_add("tcp", dissect_giop, proto_giop);
4302 * Ref Corba v2.4.2 Chapter 13
4310 typedef unsigned long ProfileId;
4312 const ProfileId TAG_INTERNET_IOP = 0;
4313 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4315 struct TaggedProfile {
4317 sequence <octet> profile_data;
4322 sequence <TaggedProfile> profiles;
4325 typedef unsigned long ComponentId;
4327 struct TaggedComponent {
4329 sequence <octet> component_data;
4332 typedef sequence <TaggedComponent> MultipleComponentProfile;
4338 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4339 guint32 boundary, gboolean stream_is_big_endian) {
4342 guint32 seqlen_p; /* sequence length of profiles */
4345 proto_tree *tree = NULL; /* IOR tree */
4348 gchar *repobuf; /* for repository ID */
4352 /* create a subtree */
4355 tf = proto_tree_add_text (ptree, tvb, *offset, tvb_length (tvb), "IOR");
4356 tree = proto_item_add_subtree (tf, ett_giop_ior);
4360 /* Get type_id == Repository ID */
4362 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4365 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4366 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4368 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4369 *offset-u_octet4,u_octet4,repobuf);
4374 * Register a cleanup function in case on of our tvbuff accesses
4375 * throws an exception. We need to clean up repobuf.
4376 * We can't free it yet, as we must wait until we have the object
4377 * key, as we have to add both to the hash table.
4379 CLEANUP_PUSH(g_free, repobuf);
4381 /* Now get a sequence of profiles */
4382 /* Get sequence length (number of elements) */
4384 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4386 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4387 *offset-sizeof(seqlen_p),4,seqlen_p);
4391 /* fetch all TaggedProfiles in this sequence */
4393 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4394 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4398 * We're done with repobuf, so we can call the cleanup handler to free
4399 * it, and then pop the cleanup handler.
4401 CLEANUP_CALL_AND_POP;
4405 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4406 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4408 guint32 seqlen_pd; /* sequence length of profile data */
4410 guint32 pidtag; /* profile ID TAG */
4412 gchar *profile_data; /* profile_data pointer */
4413 gchar *p_profile_data; /* printable profile_data pointer */
4415 guint32 new_boundary; /* for encapsulations encountered */
4416 gboolean new_big_endianess; /* for encapsulations encountered */
4418 /* Get ProfileId tag */
4420 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4423 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4424 *offset-sizeof(pidtag),4,pidtag);
4427 /* get sequence length, new endianness and boundary for encapsulation */
4429 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4430 stream_is_big_endian, boundary,
4431 &new_big_endianess, &new_boundary);
4433 /* return if zero length sequence */
4440 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4441 * decode it, otherwise just dump the octet sequence
4443 * also, store IOR in our objectkey hash
4445 * TODO - handle other TAGS
4449 case IOP_TAG_INTERNET_IOP:
4451 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4456 /* fetch all octets in this sequence , but skip endianess */
4458 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4460 /* Make a printable string */
4462 p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4465 proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4466 "Profile Data: %s", p_profile_data);
4469 g_free(p_profile_data);
4471 g_free(profile_data);
4482 * Decode IIOP IOR Profile
4483 * Ref Chap 15.7.2 in Corba Spec
4487 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4488 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4489 gboolean store_flag) {
4491 guint32 i; /* loop index */
4493 guint8 v_major,v_minor; /* IIOP sersion */
4495 guint32 u_octet4; /* u long */
4496 guint16 u_octet2; /* u short */
4497 guint32 seqlen; /* generic sequence length */
4498 guint32 seqlen1; /* generic sequence length */
4499 gchar *objkey; /* object key pointer */
4500 gchar *p_chars; /* printable characters pointer */
4503 /* Get major/minor version */
4505 v_major = get_CDR_octet(tvb,offset);
4506 v_minor = get_CDR_octet(tvb,offset);
4510 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4511 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4512 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4513 *offset-sizeof(v_minor),1,v_minor );
4519 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4522 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4523 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4525 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4526 *offset-u_octet4,u_octet4,buf);
4530 g_free(buf); /* dont forget */
4534 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4537 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4538 *offset-sizeof(u_octet2),2,u_octet2);
4542 /* Object Key - sequence<octet> object_key */
4544 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4547 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4548 *offset-sizeof(seqlen),4,seqlen);
4552 /* fetch all octets in this sequence */
4553 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4556 * Now we may have the Repository ID from earlier, as well
4557 * as the object key sequence and lengh. So lets store them in
4558 * our objectkey hash and free buffers.
4560 * But only insert if user is not clicking and repo id not NULL.
4566 if(!pinfo->fd->flags.visited)
4567 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4572 * No pinfo, but store anyway if flag set. eg: IOR read from file
4576 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4580 /* Make a printable string */
4582 p_chars = make_printable_string( objkey, seqlen );
4585 proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
4586 "Object Key: %s", p_chars);
4594 * Now see if if its v1.1 or 1.2, as they can contain
4595 * extra sequence of IOP::TaggedComponents
4608 /* sequence of IOP::TaggedComponents */
4609 /* Ref Chap 13 in Corba Spec */
4611 /* get sequence length */
4612 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4615 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4616 *offset-sizeof(seqlen),4,seqlen);
4619 for (i=0; i< seqlen; i++) {
4621 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4623 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4624 *offset-sizeof(u_octet4),4,u_octet4);
4627 /* get component_data */
4628 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4630 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4631 *offset-sizeof(seqlen1),4,seqlen1);
4635 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4638 /* Make a printable string of data */
4640 p_chars = make_printable_string(buf, seqlen1);
4642 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4643 "component_data: %s", p_chars);
4657 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4665 * Service Contexts Begin
4673 void dissect_SID_BI_DIR_IIOP(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4674 MessageHeader *header, gchar *operation, guint32 boundary) {
4684 * Service Contexts End
4696 * typedef unsigned long ServiceID;
4698 * struct ServiceContext {
4699 * ServiceID context_id;
4700 * sequence <octet> context_data;
4702 * typedef sequence <ServiceContext> ServiceContextList;
4705 * Note: Spec says context_data is an encapsulation.
4712 void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4713 gboolean stream_is_be, guint32 boundary) {
4715 guint32 seqlen; /* sequence length */
4716 guint32 seqlen_cd; /* sequence length, context_data */
4718 proto_tree *tree = NULL; /* ServiceContext tree */
4722 gchar *context_data;
4723 gchar *p_context_data;
4726 guint32 vscid; /* Vendor Service context id */
4729 /* create a subtree */
4732 tf = proto_tree_add_text (ptree, tvb, *offset, tvb_length (tvb), "ServiceContextList");
4733 tree = proto_item_add_subtree (tf, ett_giop_scl);
4736 /* Get sequence length (number of elements) */
4738 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4740 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4741 *offset-sizeof(seqlen),4,seqlen);
4744 /* return if zero length sequence */
4749 /* Loop for all ServiceContext's */
4751 for (i=0; i<seqlen; i++) {
4753 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4755 proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4756 *offset-sizeof(context_id),4,context_id);
4758 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4759 *offset-sizeof(context_id),4,context_id);
4763 vscid = context_id && 0xfffff000; /* vendor info, top 20 bits */
4764 scid = context_id && 0x00000fff; /* standard service info, lower 12 bits */
4767 #if CONTEXT_DATA_IS_ENCAPSULATED
4769 /* get sequence length, new endianness and boundary for encapsulation */
4771 seqlen_cd = get_CDR_encap_info(tvb, tree, offset,
4772 stream_is_be, boundary,
4773 &new_big_endianess, &new_boundary);
4777 /* get sequence length, and NO encapsulation */
4779 seqlen_cd = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4783 /* return if zero length sequence */
4789 * Now decode sequence according to vendor ServiceId, but I dont
4790 * have that yet, so just dump it as data.
4793 /* fetch all octets in this sequence */
4795 get_CDR_octet_seq(tvb, &context_data, offset, seqlen_cd);
4797 /* Make a printable string */
4799 p_context_data = make_printable_string( context_data, seqlen_cd );
4802 proto_tree_add_text (tree, tvb, *offset - seqlen_cd , seqlen_cd,
4803 "context_data: %s", p_context_data);
4806 g_free(context_data);
4807 g_free(p_context_data);
4812 return; /* for now, fix later */
4817 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
4820 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
4821 gboolean stream_is_big_endian,
4824 guint32 length; /* string length */
4825 guint32 minor_code_value;
4826 guint32 completion_status;
4828 gchar *buf; /* pointer to string buffer */
4830 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
4833 proto_tree_add_text(tree, tvb, *offset-4, 4,
4834 "Exception length: %u", length);
4836 proto_tree_add_text(tree, tvb, *offset - length, length,
4837 "Exception id: %s", buf );
4842 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4843 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4846 proto_tree_add_text(tree, tvb, *offset-8, 4,
4847 "Minor code value: %u", minor_code_value);
4848 proto_tree_add_text(tree, tvb, *offset-4, 4,
4849 "Completion Status: %u", completion_status);
4855 * Helper functions for dissecting TypeCodes
4857 * These functions decode the complex parameter lists
4858 * of TypeCodes as defined in the CORBA spec chapter 15.
4861 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4862 gboolean stream_is_big_endian, guint32 boundary,
4863 MessageHeader * header) {
4865 guint32 new_boundary; /* new boundary for encapsulation */
4866 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4868 guint32 seqlen; /* sequence length */
4870 /* get sequence length, new endianness and boundary for encapsulation */
4871 seqlen = get_CDR_encap_info(tvb, tree, offset,
4872 stream_is_big_endian, boundary,
4873 &new_stream_is_big_endian, &new_boundary);
4875 /* get repository ID */
4876 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4880 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4881 hf_giop_typecode_name);
4886 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4887 gboolean stream_is_big_endian, guint32 boundary,
4888 MessageHeader * header ) {
4890 guint32 new_boundary; /* new boundary for encapsulation */
4891 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4893 guint32 count; /* parameter count (of tuples) */
4894 guint32 seqlen; /* sequence length */
4895 guint32 i; /* loop index */
4897 /* get sequence lengt,h new endianness and boundary for encapsulation */
4898 seqlen = get_CDR_encap_info(tvb, tree, offset,
4899 stream_is_big_endian, boundary,
4900 &new_stream_is_big_endian, &new_boundary);
4902 /* get repository ID */
4903 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4907 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4908 hf_giop_typecode_name);
4910 /* get count of tuples */
4911 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4913 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4914 *offset-sizeof(count),4,count);
4917 /* get all tuples */
4918 for (i=0; i< count; i++) {
4919 /* get member name */
4920 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4921 hf_giop_typecode_member_name);
4923 /* get member type */
4924 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4930 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4931 gboolean stream_is_big_endian, guint32 boundary,
4932 MessageHeader * header) {
4934 guint32 new_boundary; /* new boundary for encapsulation */
4935 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4937 guint32 TCKind; /* TypeCode */
4938 gint32 s_octet4; /* signed int32 */
4940 guint32 count; /* parameter count (of tuples) */
4941 guint32 seqlen; /* sequence length */
4942 guint32 i; /* loop index */
4944 /* get sequence legnth, new endianness and boundary for encapsulation */
4945 seqlen = get_CDR_encap_info(tvb, tree, offset,
4946 stream_is_big_endian, boundary,
4947 &new_stream_is_big_endian, &new_boundary);
4949 /* get repository ID */
4950 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4954 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4955 hf_giop_typecode_name);
4957 /* get discriminant type */
4958 TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4960 /* get default used */
4961 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
4963 proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
4964 *offset-sizeof(s_octet4),4,s_octet4);
4966 /* get count of tuples */
4967 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4969 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4970 *offset-sizeof(count),4,count);
4973 /* get all tuples */
4974 for (i=0; i< count; i++) {
4975 /* get label value, based on TCKind above */
4976 dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
4978 /* get member name */
4979 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4980 hf_giop_typecode_member_name);
4982 /* get member type */
4983 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4989 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4990 gboolean stream_is_big_endian, guint32 boundary,
4991 MessageHeader * header) {
4993 guint32 new_boundary; /* new boundary for encapsulation */
4994 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4996 guint32 count; /* parameter count (of tuples) */
4997 guint32 seqlen; /* sequence length */
4998 guint32 i; /* loop index */
5000 /* get sequence length, new endianness and boundary for encapsulation */
5001 seqlen = get_CDR_encap_info(tvb, tree, offset,
5002 stream_is_big_endian, boundary,
5003 &new_stream_is_big_endian, &new_boundary);
5005 /* get repository ID */
5006 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5010 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5011 hf_giop_typecode_name);
5013 /* get count of tuples */
5014 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5016 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5017 *offset-sizeof(count),4,count);
5020 /* get all tuples */
5021 for (i=0; i< count; i++) {
5022 /* get member name */
5023 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5024 hf_giop_typecode_member_name);
5030 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5031 gboolean stream_is_big_endian, guint32 boundary,
5032 MessageHeader * header) {
5034 guint32 new_boundary; /* new boundary for encapsulation */
5035 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5037 guint32 u_octet4; /* unsigned int32 */
5039 guint32 seqlen; /* sequence length */
5041 /* get sequence length, new endianness and boundary for encapsulation */
5042 seqlen = get_CDR_encap_info(tvb, tree, offset,
5043 stream_is_big_endian, boundary,
5044 &new_stream_is_big_endian, &new_boundary);
5046 /* get element type */
5047 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5049 /* get max length */
5050 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5052 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
5053 *offset-sizeof(u_octet4),4,u_octet4);
5058 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5059 gboolean stream_is_big_endian, guint32 boundary,
5060 MessageHeader * header) {
5062 guint32 new_boundary; /* new boundary for encapsulation */
5063 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5065 guint32 u_octet4; /* unsigned int32 */
5067 guint32 seqlen; /* sequence length */
5069 /* get sequence length, new endianness and boundary for encapsulation */
5070 seqlen = get_CDR_encap_info(tvb, tree, offset,
5071 stream_is_big_endian, boundary,
5072 &new_stream_is_big_endian, &new_boundary);
5074 /* get element type */
5075 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5078 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5080 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5081 *offset-sizeof(u_octet4),4,u_octet4);
5086 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5087 gboolean stream_is_big_endian, guint32 boundary,
5088 MessageHeader * header) {
5090 guint32 new_boundary; /* new boundary for encapsulation */
5091 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5093 guint32 seqlen; /* sequence length */
5095 /* get sequence legnth, new endianness and boundary for encapsulation */
5096 seqlen = get_CDR_encap_info(tvb, tree, offset,
5097 stream_is_big_endian, boundary,
5098 &new_stream_is_big_endian, &new_boundary);
5100 /* get repository ID */
5101 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5105 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5106 hf_giop_typecode_name);
5108 /* get ??? (noname) TypeCode */
5109 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5114 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5115 gboolean stream_is_big_endian, guint32 boundary,
5116 MessageHeader * header) {
5118 guint32 new_boundary; /* new boundary for encapsulation */
5119 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5121 guint32 count; /* parameter count (of tuples) */
5122 guint32 seqlen; /* sequence length */
5123 guint32 i; /* loop index */
5125 /* get sequence length, new endianness and boundary for encapsulation */
5126 seqlen = get_CDR_encap_info(tvb, tree, offset,
5127 stream_is_big_endian, boundary,
5128 &new_stream_is_big_endian, &new_boundary);
5130 /* get repository ID */
5131 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5135 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5136 hf_giop_typecode_name);
5138 /* get count of tuples */
5139 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5141 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5142 *offset-sizeof(count),4,count);
5145 /* get all tuples */
5146 for (i=0; i< count; i++) {
5147 /* get member name */
5148 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5149 hf_giop_typecode_member_name);
5151 /* get member type */
5152 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5158 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5159 gboolean stream_is_big_endian, guint32 boundary,
5160 MessageHeader * header) {
5162 guint32 new_boundary; /* new boundary for encapsulation */
5163 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5165 gint16 s_octet2; /* signed int16 */
5167 guint32 count; /* parameter count (of tuples) */
5168 guint32 seqlen; /* sequence length */
5169 guint32 i; /* loop index */
5171 /* get sequence length, new endianness and boundary for encapsulation */
5172 seqlen = get_CDR_encap_info(tvb, tree, offset,
5173 stream_is_big_endian, boundary,
5174 &new_stream_is_big_endian, &new_boundary);
5176 /* get repository ID */
5177 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5181 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5182 hf_giop_typecode_name);
5184 /* get ValueModifier */
5185 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5187 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5188 *offset-sizeof(s_octet2),2,s_octet2);
5191 /* get conrete base */
5192 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5194 /* get count of tuples */
5195 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5197 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5198 *offset-sizeof(count),4,count);
5201 /* get all tuples */
5202 for (i=0; i< count; i++) {
5203 /* get member name */
5204 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5205 hf_giop_typecode_member_name);
5207 /* get member type */
5208 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5210 /* get Visibility */
5211 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5213 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5214 *offset-sizeof(s_octet2),2,s_octet2);
5221 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5222 gboolean stream_is_big_endian, guint32 boundary,
5223 MessageHeader * header) {
5225 guint32 new_boundary; /* new boundary for encapsulation */
5226 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5228 guint32 seqlen; /* sequence length */
5230 /* get sequence length, new endianness and boundary for encapsulation */
5231 seqlen = get_CDR_encap_info(tvb, tree, offset,
5232 stream_is_big_endian, boundary,
5233 &new_stream_is_big_endian, &new_boundary);
5235 /* get repository ID */
5236 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5240 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5241 hf_giop_typecode_name);
5243 /* get ??? (noname) TypeCode */
5244 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5248 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5249 gboolean stream_is_big_endian, guint32 boundary,
5250 MessageHeader * header) {
5252 guint32 new_boundary; /* new boundary for encapsulation */
5253 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5255 guint32 seqlen; /* sequence length */
5257 /* get sequence length, new endianness and boundary for encapsulation */
5258 seqlen = get_CDR_encap_info(tvb, tree, offset,
5259 stream_is_big_endian, boundary,
5260 &new_stream_is_big_endian, &new_boundary);
5262 /* get repository ID */
5263 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5267 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5268 hf_giop_typecode_name);
5273 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5274 gboolean stream_is_big_endian, guint32 boundary,
5275 MessageHeader * header) {
5277 guint32 new_boundary; /* new boundary for encapsulation */
5278 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5280 guint32 seqlen; /* sequence length */
5282 /* get sequence length, new endianness and boundary for encapsulation */
5283 seqlen = get_CDR_encap_info(tvb, tree, offset,
5284 stream_is_big_endian, boundary,
5285 &new_stream_is_big_endian, &new_boundary);
5287 /* get repository ID */
5288 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5292 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5293 hf_giop_typecode_name);
5297 /* Typecode parameter lists are encoded as encapsulations and
5298 * this function gets the encapsulation information; see
5299 * CORBA spec chapter 15
5302 * Renamed to get_CDR_encap_info() for any encapsulation
5303 * we come across, useful helper function
5305 * Also, should return immediately if seqlen == 0.
5306 * ie: Forget about trying to grab endianess for
5307 * zero length sequence.
5309 * Caller must always check seqlen == 0, and not assume its value
5312 * Note: there seemed to be considerable confusion in corba
5313 * circles as to the correct interpretation of encapsulations,
5314 * and zero length sequences etc, but this is our best bet at the
5321 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5322 gboolean old_stream_is_big_endian, guint32 old_boundary,
5323 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5325 guint32 seqlen; /* sequence length */
5326 guint8 giop_endianess;
5328 /* Get sequence length of parameter list */
5329 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5331 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5332 *offset-sizeof(seqlen),4,seqlen);
5338 * seqlen == 0, implies no endianess and no data
5339 * so just return. Populate new_boundary_ptr and
5340 * new_stream_is_big_endian_ptr with current (old)
5341 * values, just to keep everyone happy. -- FS
5347 *new_boundary_ptr = old_boundary;
5348 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5354 /* Start of encapsulation of parameter list */
5355 *new_boundary_ptr = *offset; /* remember */
5356 giop_endianess = get_CDR_octet(tvb,offset);
5358 *new_stream_is_big_endian_ptr = ! giop_endianess;
5361 * Glib: typedef gint gboolean;
5362 * ie: It is not a guint8, so cannot use sizeof to correctly
5368 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5369 *offset-1,1,giop_endianess);
5379 * gets a TypeCode complex string parameter and
5380 * displays it in the relevant tree.
5383 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5384 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5386 guint32 u_octet4; /* unsigned int32 */
5387 gchar *buf; /* ptr to string buffer */
5390 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5393 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5394 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5396 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5400 g_free(buf); /* dont forget */
5405 * For a given data type, given by a TypeCode gets the associated data
5406 * and displays it in the relevant tree.
5409 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5410 gboolean stream_is_big_endian, guint32 boundary,
5411 MessageHeader * header, guint32 data_type ) {
5413 gboolean my_boolean; /* boolean */
5415 gint8 s_octet1; /* signed int8 */
5416 guint8 u_octet1; /* unsigned int8 */
5418 gint16 s_octet2; /* signed int16 */
5419 guint16 u_octet2; /* unsigned int16 */
5421 gint32 s_octet4; /* signed int32 */
5422 guint32 u_octet4; /* unsigned int32 */
5424 gdouble my_double; /* double */
5425 gfloat my_float; /* float */
5427 gchar *buf = NULL; /* ptr to string buffer */
5429 /* Grab the data according to data type */
5431 switch (data_type) {
5433 /* nothing to decode */
5436 /* nothing to decode */
5439 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5441 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5442 *offset-sizeof(s_octet2),2,s_octet2);
5446 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5448 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5449 *offset-sizeof(s_octet4),4,s_octet4);
5453 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5455 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5456 *offset-sizeof(u_octet2),2,u_octet2);
5460 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5462 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5463 *offset-sizeof(u_octet4),4,u_octet4);
5467 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5469 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5470 *offset-sizeof(my_float),4,my_float);
5474 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5476 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5477 *offset-sizeof(my_double),8,my_double);
5481 my_boolean = get_CDR_boolean(tvb,offset);
5483 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5484 *offset-1,1,my_boolean);
5488 u_octet1 = get_CDR_char(tvb,offset);
5490 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5491 *offset-sizeof(u_octet1),1,u_octet1);
5495 u_octet1 = get_CDR_octet(tvb,offset);
5497 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5498 *offset-sizeof(u_octet1),1,u_octet1);
5502 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5505 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5516 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5518 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5519 *offset-sizeof(u_octet4),4,u_octet4);
5523 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5525 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5526 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5528 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5529 *offset-u_octet4,u_octet4,buf);
5533 g_free(buf); /* dont forget */
5550 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5553 * XXX - can any of these throw an exception?
5554 * If so, we need to catch the exception and free "buf".
5556 if (s_octet1 < 0) { /* no size to add to tree */
5557 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5558 *offset+s_octet1,(-s_octet1),buf);
5560 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5561 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5562 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5563 *offset-s_octet1,s_octet1,buf);
5567 g_free(buf); /* dont forget */
5570 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5573 * XXX - can any of these throw an exception?
5574 * If so, we need to catch the exception and free "buf".
5576 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5577 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5578 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5579 *offset-u_octet4,u_octet4,buf);
5582 g_free(buf); /* dont forget */
5592 case tk_abstract_interface:
5595 g_warning("giop: Unknown typecode data type %u \n", data_type);