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.57 2002/02/27 00:30:22 guy Exp $
14 * Ethereal - Network traffic analyzer
15 * By Gerald Combs <gerald@ethereal.com>
16 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 * 1. heuristic giop dissector table [started]
37 * 2. GUI options, see 20
38 * 3. Remove unneccessary reply_status in heuristic dissector calls (now
39 * part of MessageHeader) [done]
40 * 4. get_CDR_xxx should be passed an alignment offset value
41 * rather than GIOP_HEADER_SIZE, as alignment can also change in a
42 * octet stream when eg: encapsulation is used [done]
43 * 5. GIOP users should eventually get there own tvbuff, and
44 * not rely on the GIOP tvbuff, more robust
45 * 6. get_CDR_string,wchar,wstring etc should handle different
46 * GIOP versions [started]
47 * 7. Fix situation where req_id is not unique in a logfile [done, use FN/MFN, needs improving.]
49 * 8. Keep request_1_2 in step with request_1_1 [started]
50 * 9. Explicit module name dissection [done]
51 * 10. Decode IOR and put in a useful struct [IOR decode started]
52 * 11. Fix encapsulation of IOR etc and boundary [done]
53 * 12. handle get_CDR_typeCode() [started]
54 * 13. Handle different IOR profiles
55 * 14. Change printable_string to RETURN a new string, not to modify the old.
56 * or, new function, make_printable_string [done, make_printable_string]
58 * 15. Handle "TCKind", and forget about eg: enum translation to symbolic values
59 * otherwise need knowledge of sub dissectors data - YUK [done]
60 * 16. Handle multiple RepoId representations, besides IDL:Echo:1.0 (see 13.)
61 * 17. Pass subset of RepoID to explicit dissector.
62 * eg : If IDL:Mod1/Mod2/Int3:1.0 then pass "Mod1/Mode2/Int3" to sub dissector[done]
63 * 18. Better hashing algorithms
64 * 19. Handle hash collision properly .
65 * 20. Allow users to paste a stringified IOR into the GUI, and tie it
67 * 21. Add complete_request_packet_list and complete_reply_packet_hash.[done]
68 * 22. Handle case where users click in any order, AND try and match
69 * REPLY msg to the correct REQUEST msg when we have a request_id collision.[done]
70 * 23. Clean up memory management for all those g_malloc's etc
71 * 24. register_giop_user_module could return a key for every distinct Module/Interface
72 * the sub_dissector uses. So, instead of strcmp()'s when handling the
73 * namespace of an operation, we could have a lookup table instead.
74 * 25. A few typedefs in the right place.
75 * 26 Improve handling of gchar * and use const gchar * where possible.
76 * 27. Read/write IOR etc to/from file, allows objkey hash to be built from
77 * external data [read done, write incomplete]
78 * 28. Call sub dissector only if tvb_offset_exists(). [Done, this is checked
79 * inside try_explicit_giop_dissector() ]
81 * 29. Make add/delete routine for objkey hash as it may be useful when say reading
82 * stringified IOR's from a file to add them to our hash. ie: There are other ways
83 * to populate our object key hash besides REPLY's to RESOLVE(request) [done]
85 * 30. Add routine to encode/decode stringified IOR's [decode done]
86 * 31. Add routine to read IOR's from file [done]
87 * 32. TypeCode -none-, needs decoding.
88 * 33. Complete dissect_data_for_typecode.
89 * 34. For complex TypeCodes need to check final offset against original offset + sequence length.
90 * 35. Update REQUEST/REPLY 1_2 according to IDL (eg; ServiceContextList etc).
91 * 36. Adding decode_ServiceContextList, incomplete.
92 * 37. Helper functions should not ALWAYS rely on header to find current endianess. It should
93 * be passed from user, eg Use stream_is_big_endian. [started]
94 * 38. Remove unwanted/unused function parameters, see decode_IOR [started]
95 * 40. Add sequence <IOP::TaggedComponent> components to IIOP IOR profile. Perhaps
96 * decode_IOP_TaggedComponents as a helper function. [done - NOT helper]
98 * 41. Make important field searchable from Message header. ie: Remove add_text_
99 * 42. Use sub-tree for decode_ServiceContextList, looks better.
100 * 43. dissect_reply_body, no exception dissector calls
101 * - call subdiss directly, as we already have handle.
102 * - add repoid to heuristic call also.
104 * 44. typedef using xxx_t in .h file.
105 * 45. Subdissectors should not be passed MessageHeader to find endianness and
106 * version, they should be passed directly ?
107 * 46. get_CDR_wchar and wstring need wide chars decoded (just dumped in
108 * any readable form at present, not handled well at all, suggestions welcome -- FS
109 * 47. Change ...add_text to ...add_xxx (ie use hf fields).
111 * 48. BUG - file load with a GIOP filter set, causes the FN/MFN data struct to be
112 * not initiated properly. Hit "Reload" as a workaround, til I fix this -- FS
119 * Intended Decode strategy:
120 * =========================
124 * REQUEST: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
125 * and populate complete_request_packet_hash
127 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
132 * REQUEST: FN -> giop_sub_handle_t directly (via complete_request_packet_hash)
134 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
135 * (via complete_request_packet_hash
141 * 1. Request_ID's are unique only per connection.
143 * 2. You must be monitoring the network when the client does
144 * a REQUEST(resolve), otherwise I have no knowledge of the
145 * association between object_key and REPOID. I could talk to
146 * a Nameserver, but then I would start "generating" packets.
147 * This is probably not a good thing for a protocol analyser.
148 * Also, how could I decode logfiles offline.
150 * TODO -- Read stringified IORs from an input file.[done]
152 * 3. User clicks (REQUEST) is currently handle the same as
153 * the initial pass handling.
155 * ie: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
160 * Important Data Structures:
165 * This is a hash table that maps IDL Module/Interface Names (Key)
166 * to sub_dissector handles, giop_sub_handle_t. It is populated
167 * by subdissectors, via register_giop_user_module(). This
168 * table is used when we have a REPOID, and explicitly wish to
169 * call the subdissector that has registered responsibility for
170 * that IDL module/interface.
176 * This singly linked list is used to hold entries for
177 * heuristic based subdissectors. It is populated by sub_dissectors
178 * wishing to be called via heuristic mechanisms. They do this
179 * via the register_giop_user() function.
185 * This hash table maps object_key's (key) onto REPOID's (val).
186 * Once a client has REQUEST(resolve) an object , it knows about
187 * an object (interface) via its object_key (see IOR). So in order to follow
188 * packets that contain an object_key only, and to be able to forward it
189 * to the correct explicit subdissector, we need this table.
191 * So, I listen in on REQUEST(resolve) messages between client and
192 * Nameserver, and store the respones (REPLY/Objkey,Repo_ID) here.
194 * Also, stringified IOR's can be read from a file "IOR.txt" and used
195 * to populate this hash also.
198 * Other Data structures
199 * =======================
201 * These structures have been added to minimise the possibility
202 * of incorrectly interpreted packets when people click all
203 * over the place, in no particular order, when the request_id's are
204 * not unique as captured. If all request_is'd are unique, as captured, then
205 * we would not have to deal with this problem.
208 * When the logfile or packets are initially being processed, I will
209 * build 2 structures. The intent is to be able to map a REPLY message
210 * back to the most recent REQUEST message with the same Request_ID
211 * (TODO and matching port and IP address ??)
217 * MFN - Matching Frame Number
220 * complete_request_packet_list
221 * ----------------------------
223 * This is a list that contains ALL the FN's that are REQUEST's, along with
224 * operation,request_id and giop_sub_handle_t
226 * complete_reply_packet_hash
227 * --------------------------
229 * This is a hash table. It is populated with FN (key) and MFN (val).
230 * This allows me to handle the case, where if you click on any REPLY
231 * message, I can lookup the matching request. This can improve
232 * the match rate between REQUEST and REPLY when people click in
233 * any old fashion, but is NOT foolproof.
235 * The algorithm I use to populate this hash during initial pass,
238 * If packet is a REPLY, note the reqid, and then traverse backwards
239 * through the complete_request_packet_list from its tail, looking
240 * for a FN that has the same Request_id. Once found, take the found FN
241 * from complete_reply_packet_hash, and insert it into the MFN field
242 * of the complete_reply_packet_hash.
245 * See TODO for improvements to above algorithm.
247 * So now when people click on a REQUEST packet, I can call lookup the
248 * giop_sub_handle_t directly from complete_request_packet_list.
250 * And, when they click on a REPLY, I grab the MFN of this FN from
251 * complete_reply_packet_hash, then look that up in the complete_request_packet_list
252 * and call the sub_dissector directly.
254 * So, how do I differentiate between the initial processing of incoming
255 * packets, and a user clickin on one ? Good question.
257 * I leverage the pinfo_fd->flags.visited on a per frame
260 * To quote from the ever helpful development list
262 * " When a capture file is initially loaded, all "visited" flags
263 * are 0. Ethereal then makes the first pass through file,
264 * sequentially dissecting each packet. After the packet is
265 * dissected the first time, "visited" is 1. (See the end of
266 * dissect_packet() in epan/packet.c; that's the code that
267 * sets "visited" to 1).
269 * By the time a user clicks on a packet, "visited" will already
270 * be 1 because Ethereal will have already done its first pass
271 * through the packets.
273 * Reload acts just like a normal Close/Open, except that it
274 * doesn't need to ask for a filename. So yes, the reload button
275 * clears the flags and re-dissects the file, just as if the file
276 * had been "opened". "
285 #ifdef HAVE_SYS_TYPES_H
286 # include <sys/types.h>
295 #ifdef NEED_STRERROR_H
296 #include "strerror.h"
299 #include <epan/packet.h>
300 #include "packet-giop.h"
303 * This affects how we handle context_data inside ServiceContext structs.
304 * According to CORBA 2.4.2, Context data is encapsulated in octet sequences,
305 * but so far I haven't seen the that on the wire. But, maybe its me -- FS
309 #define CONTEXT_DATA_IS_ENCAPSULATED 0
313 * Set to 1 for DEBUG output - TODO make this a runtime option
321 * ------------------------------------------------------------------------------------------+
322 * Private Helper function Declarations
323 * ------------------------------------------------------------------------------------------+
327 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
328 guint32 boundary, gboolean new_endianess, gchar *repobuf,
329 gboolean store_flag);
331 static void decode_ServiceContextList(tvbuff_t *tvb, 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 */
468 static dissector_handle_t data_handle;
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);
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;
1743 const char *saved_proto;
1745 len = g_slist_length(giop_sub_list); /* find length */
1750 saved_proto = pinfo->current_proto;
1751 for (i=0; i<len; i++) {
1752 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1754 if (proto_is_protocol_enabled(subh->sub_proto)) {
1755 pinfo->current_proto =
1756 proto_get_protocol_short_name(subh->sub_proto);
1757 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1759 pinfo->current_proto = saved_proto;
1760 return TRUE; /* found one, lets return */
1762 } /* protocol_is_enabled */
1765 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1766 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
1768 pinfo->current_proto = saved_proto;
1769 return res; /* result */
1775 * Find the matching repoid in the module hash and call
1776 * the dissector function if offset exists.
1779 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1780 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1786 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1787 MessageHeader *header, gchar *operation, gchar *repoid ) {
1789 giop_sub_handle_t *subdiss = NULL; /* handle */
1790 gboolean res = FALSE;
1791 gchar *modname = NULL;
1792 struct giop_module_key module_key;
1793 struct giop_module_val *module_val = NULL;
1794 const char *saved_proto;
1798 * Get top level module/interface from complete repoid
1801 modname = get_modname_from_repoid(repoid);
1802 if (modname == NULL) {
1803 return res; /* unknown module name */
1807 /* Search for Module or interface name */
1809 module_key.module = modname; /* module name */
1810 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1812 if (module_val == NULL) {
1813 return res; /* module not registered */
1816 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1819 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1820 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1821 /* but only if user not clicking */
1823 if (!pinfo->fd->flags.visited)
1824 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1827 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1829 if (tvb_offset_exists(tvb, *offset)) {
1831 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1834 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1836 saved_proto = pinfo->current_proto;
1837 pinfo->current_proto =
1838 proto_get_protocol_short_name(subdiss->sub_proto);
1839 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1840 pinfo->current_proto = saved_proto;
1842 } /* protocol_is_enabled */
1843 } /* offset exists */
1846 return res; /* return result */
1851 /* Take in an array of char and create a new string.
1852 * Replace non-printable characters with periods.
1854 * The array may contain \0's so dont use strdup
1855 * The string is \0 terminated, and thus longer than
1856 * the initial sequence.
1857 * Caller must free the new string.
1860 static gchar * make_printable_string (gchar *in, guint32 len) {
1862 gchar *print_string = NULL;
1864 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1865 memcpy(print_string, in, len); /* and make a copy of input data */
1867 for(i=0; i < len; i++) {
1868 if( !isprint( (unsigned char)print_string[i] ) )
1869 print_string[i] = '.';
1872 return print_string; /* return ptr */
1875 /* Determine the byte order from the GIOP MessageHeader */
1877 gboolean is_big_endian (MessageHeader * header) {
1878 gboolean big_endian = FALSE;
1880 switch (header->GIOP_version.minor) {
1883 if (header->flags & 0x01)
1903 * Calculate new offset, based on the current offset, and user supplied
1904 * "offset delta" value, and the alignment requirement.
1908 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1909 * aligned on 8 byte boundaries.
1912 static void set_new_alignment(int *offset, int delta, int alignment) {
1914 while( ( (*offset + delta) % alignment) != 0)
1923 * ------------------------------------------------------------------------------------------+
1924 * Public get_CDR_xxx functions.
1925 * ------------------------------------------------------------------------------------------+
1931 * Gets data of type any. This is encoded as a TypeCode
1932 * followed by the encoded value.
1935 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1936 gboolean stream_is_big_endian, int boundary,
1937 MessageHeader * header ) {
1939 guint32 TCKind; /* TypeCode */
1941 /* get TypeCode of any */
1942 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1944 /* dissect data of type TCKind */
1945 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1949 /* Copy a 1 octet sequence from the tvbuff
1950 * which represents a boolean value, and convert
1951 * it to a boolean value.
1952 * Offset is then incremented by 1, to indicate the 1 octet which
1953 * has been processed.
1956 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1959 val = tvb_get_guint8(tvb, *offset); /* easy */
1964 /* Copy a 1 octet sequence from the tvbuff
1965 * which represents a char, and convert
1966 * it to an char value.
1967 * offset is then incremented by 1, to indicate the 1 octet which
1968 * has been processed.
1971 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1974 val = tvb_get_guint8(tvb, *offset); /* easy */
1982 * Floating Point Data Type double IEEE 754-1985
1984 * Copy an 8 octet sequence from the tvbuff
1985 * which represents a double value, and convert
1986 * it to a double value, taking into account byte order.
1987 * offset is first incremented so that it falls on a proper alignment
1988 * boundary for double values.
1989 * offset is then incremented by 8, to indicate the 8 octets which
1990 * have been processed.
1993 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1996 guint8 e1,e2,f1,f2,f3,f4,f5,f6,f7;
1999 guint32 fract0, fract1;
2003 /* double values must be aligned on a 8 byte boundary */
2005 while( ( (*offset + boundary) % 8) != 0)
2009 if(stream_is_big_endian) {
2010 e1 = get_CDR_octet(tvb,offset);
2011 sign = e1 >> 7; /* sign value */
2012 e1 &= 0x7f; /* bottom 7 bits */
2013 f1 = get_CDR_octet(tvb,offset);
2015 f1 &= 0x0f; /* bottom 4 bits */
2016 f2 = get_CDR_octet(tvb,offset);
2017 f3 = get_CDR_octet(tvb,offset);
2018 f4 = get_CDR_octet(tvb,offset);
2019 f5 = get_CDR_octet(tvb,offset);
2020 f6 = get_CDR_octet(tvb,offset);
2021 f7 = get_CDR_octet(tvb,offset);
2025 f7 = get_CDR_octet(tvb,offset);
2026 f6 = get_CDR_octet(tvb,offset);
2027 f5 = get_CDR_octet(tvb,offset);
2028 f4 = get_CDR_octet(tvb,offset);
2029 f3 = get_CDR_octet(tvb,offset);
2030 f2 = get_CDR_octet(tvb,offset);
2031 f1 = get_CDR_octet(tvb,offset);
2033 f1 &= 0x0f; /* bottom 4 bits */
2034 e1 = get_CDR_octet(tvb,offset);
2035 sign = e1 >> 7; /* sign value */
2036 e1 &= 0x7f; /* bottom 7 bits */
2040 exp = (e1 << 4) + e2;
2042 /* Now lets do some 52 bit math with 32 bit constraint */
2044 fract0 = f7 + (f6 << 8) + (f5 << 16) + (f4 << 24); /* lower 32 bits of fractional part */
2045 fract1 = f3 + (f2 << 8) + (f1 << 16); /* top 20 bits of fractional part */
2047 d_fract = (fract1 / (pow(2,20))) + (fract0 / (pow(2,52))); /* 52 bits represent a fraction */
2049 val = pow(-1,sign) * pow(2,(exp - 1023)) * (1 + d_fract);
2051 return val; /* FIX rounding ?? */
2056 /* Copy a 4 octet sequence from the tvbuff
2057 * which represents an enum value, and convert
2058 * it to an enum value, taking into account byte order.
2059 * offset is first incremented so that it falls on a proper alignment
2060 * boundary for an enum (4)
2061 * offset is then incremented by 4, to indicate the 4 octets which
2062 * have been processed.
2064 * Enum values are encoded as unsigned long.
2068 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2070 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2076 * Copy an octet sequence from the tvbuff
2077 * which represents a Fixed point decimal type, and create a string representing
2078 * a Fixed point decimal type. There are no alignment restrictions.
2079 * Size and scale of fixed decimal type is determined by IDL.
2081 * digits - IDL specified number of "digits" for this fixed type
2082 * scale - IDL specified "scale" for this fixed type
2085 * eg: typedef fixed <5,2> fixed_t;
2086 * could represent numbers like 123.45, 789.12,
2089 * As the fixed type could be any size, I will not try to fit it into our
2090 * simple types like gdouble or glong etc. I will just create a string buffer holding
2091 * a representation (after scale is applied), and with a decimal point or zero padding
2092 * inserted at the right place if necessary. The string is null terminated
2094 * so string may look like
2097 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2099 * According to spec, digits <= 31
2100 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2103 * User must remember to free the buffer
2108 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2110 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2111 guint32 i ; /* loop */
2112 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2113 /* this does not include sign, decimal point and \0 */
2114 guint32 sindex = 0; /* string index */
2115 gchar *tmpbuf; /* temp buff, holds string without scaling */
2116 guint8 tval; /* temp val storage */
2119 * how many bytes to hold digits and scale (if scale <0)
2121 * eg: fixed <5,2> = 5 digits
2122 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2126 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2130 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2132 slen = digits; /* digits */
2136 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2139 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2142 * Register a cleanup function in case on of our tvbuff accesses
2143 * throws an exception. We need to clean up tmpbuf.
2145 CLEANUP_PUSH(g_free, tmpbuf);
2147 /* If even , grab 1st dig */
2149 if (!(digits & 0x01)) {
2150 tval = get_CDR_octet(tvb,offset);
2152 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2154 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2159 * Loop, but stop BEFORE we hit last digit and sign
2160 * if digits = 1 or 2, then this part is skipped
2164 for(i=0; i< ((digits-1)/2 ); i++) {
2165 tval = get_CDR_octet(tvb,offset);
2167 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2170 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2172 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2179 printf("giop:get_CDR_fixed(): before last digit \n");
2183 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2185 tval = get_CDR_octet(tvb,offset);
2187 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2189 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2192 sign = tval & 0x0f; /* get sign */
2194 /* So now, we have all digits in an array, and the sign byte
2195 * so lets generate a printable string, taking into account the scale
2199 sindex = 0; /* reset */
2200 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2201 * \0 -- TODO check slen is reasonable first */
2203 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2208 (*seq)[sindex] = '+'; /* put sign in first string position */
2211 (*seq)[sindex] = '-';
2214 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2215 (*seq)[sindex] = '*'; /* flag as sign unkown */
2221 /* Add decimal point or padding 0's, depending if scale is positive or
2222 * negative, respectively
2226 for (i=0; i<digits-scale; i++) {
2227 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2231 (*seq)[sindex] = '.'; /* decimal point */
2234 for (i=digits-scale; i<digits; i++) {
2235 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2239 (*seq)[sindex] = '\0'; /* string terminator */
2243 /* negative scale, dump digits and pad out with 0's */
2245 for (i=0; i<digits-scale; i++) {
2247 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2249 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2254 (*seq)[sindex] = '\0'; /* string terminator */
2259 * We're done with tmpbuf, so we can call the cleanup handler to free
2260 * it, and then pop the cleanup handler.
2262 CLEANUP_CALL_AND_POP;
2265 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2275 * Floating Point Data Type float IEEE 754-1985
2277 * Copy an 4 octet sequence from the tvbuff
2278 * which represents a float value, and convert
2279 * it to a float value, taking into account byte order.
2280 * offset is first incremented so that it falls on a proper alignment
2281 * boundary for float values.
2282 * offset is then incremented by 4, to indicate the 4 octets which
2283 * have been processed.
2286 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2289 guint8 e1,e2,f1,f2,f3;
2295 /* float values must be aligned on a 4 byte boundary */
2297 while( ( (*offset + boundary) % 4) != 0)
2300 if(stream_is_big_endian) {
2301 e1 = get_CDR_octet(tvb,offset);
2302 sign = e1 >> 7; /* sign value */
2303 e1 &= 0x7f; /* bottom 7 bits */
2304 f1 = get_CDR_octet(tvb,offset);
2306 f1 &= 0x7f; /* bottom 7 bits */
2307 f2 = get_CDR_octet(tvb,offset);
2308 f3 = get_CDR_octet(tvb,offset);
2312 f3 = get_CDR_octet(tvb,offset);
2313 f2 = get_CDR_octet(tvb,offset);
2314 f1 = get_CDR_octet(tvb,offset);
2316 f1 &= 0x7f; /* bottom 7 bits */
2317 e1 = get_CDR_octet(tvb,offset);
2318 sign = e1 >> 7; /* sign value */
2319 e1 &= 0x7f; /* bottom 7 bits */
2324 exp = (e1 << 1) + e2;
2325 fract = f3 + (f2 << 8) + (f1 << 16);
2327 d_fract = fract / (pow(2,23)); /* 23 bits represent a fraction */
2329 val = pow(-1,sign) * pow(2,(exp - 127)) * (1 + d_fract);
2331 return val; /* FIX rounding ?? */
2337 * Decode an Interface type, and display it on the tree.
2340 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2341 gboolean stream_is_big_endian, int boundary) {
2344 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2350 /* Copy a 4 octet sequence from the tvbuff
2351 * which represents a signed long value, and convert
2352 * it to an signed long vaule, taking into account byte order.
2353 * offset is first incremented so that it falls on a proper alignment
2354 * boundary for long values.
2355 * offset is then incremented by 4, to indicate the 4 octets which
2356 * have been processed.
2359 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2363 /* unsigned long values must be aligned on a 4 byte boundary */
2364 while( ( (*offset + boundary) % 4) != 0)
2367 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2368 tvb_get_letohl (tvb, *offset);
2375 * Decode an Object type, and display it on the tree.
2378 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2379 gboolean stream_is_big_endian, int boundary) {
2381 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2387 /* Copy a 1 octet sequence from the tvbuff
2388 * which represents a octet, and convert
2389 * it to an octet value.
2390 * offset is then incremented by 1, to indicate the 1 octet which
2391 * has been processed.
2394 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2397 val = tvb_get_guint8(tvb, *offset); /* easy */
2403 /* Copy a sequence of octets from the tvbuff.
2404 * Caller of this function must remember to free the
2405 * array pointed to by seq.
2406 * This function also increments offset by len.
2409 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, int len) {
2411 if (! tvb_bytes_exist(tvb, *offset,len)) {
2413 * Generate an exception, and stop processing.
2414 * We do that now, rather than after allocating the buffer, so we
2415 * don't have to worry about freeing the buffer.
2416 * XXX - would we be better off using a cleanup routine?
2418 tvb_get_guint8(tvb, *offset + len);
2422 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2423 * do what we do now, and null-terminate the string (which also means
2424 * we don't need to zero out the entire allocation, just the last byte)?
2426 *seq = g_new0(gchar, len + 1);
2427 tvb_memcpy( tvb, *seq, *offset, len);
2432 /* Copy a 2 octet sequence from the tvbuff
2433 * which represents a signed short value, and convert
2434 * it to a signed short value, taking into account byte order.
2435 * offset is first incremented so that it falls on a proper alignment
2436 * boundary for short values.
2437 * offset is then incremented by 2, to indicate the 2 octets which
2438 * have been processed.
2441 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2445 /* short values must be aligned on a 2 byte boundary */
2446 while( ( (*offset + boundary) % 2) != 0)
2449 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2450 tvb_get_letohs (tvb, *offset);
2458 /* Copy an octet sequence from the tvbuff
2459 * which represents a string, and convert
2460 * it to an string value, taking into account byte order.
2461 * offset is first incremented so that it falls on a proper alignment
2462 * boundary for string values. (begins with an unsigned long LI)
2464 * String sequence is copied to a buffer "seq". This must
2465 * be freed by the calling program.
2466 * offset is then incremented, to indicate the octets which
2467 * have been processed.
2469 * returns number of octets in the sequence
2471 * Note: This function only supports single byte encoding at the
2472 * moment until I get a handle on multibyte encoding etc.
2477 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2482 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2485 (*offset)++; /* must step past \0 delimiter */
2489 get_CDR_octet_seq(tvb, seq, offset, slength);
2491 *seq = g_strdup(""); /* zero-length string */
2494 return slength; /* return length */
2498 /* Process a sequence of octets that represent the
2499 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2501 * This function also increments offset to the correct position.
2503 * It will parse the TypeCode and output data to the "tree" provided
2506 * It returns a guint32 representing a TCKind value.
2509 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2510 gboolean stream_is_big_endian, int boundary,
2511 MessageHeader * header ) {
2514 gint16 s_octet2; /* signed int16 */
2515 guint16 u_octet2; /* unsigned int16 */
2516 guint32 u_octet4; /* unsigned int32 */
2518 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2520 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2521 *offset-sizeof(val),4,val);
2524 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2527 case tk_null: /* empty parameter list */
2529 case tk_void: /* empty parameter list */
2531 case tk_short: /* empty parameter list */
2533 case tk_long: /* empty parameter list */
2535 case tk_ushort: /* empty parameter list */
2537 case tk_ulong: /* empty parameter list */
2539 case tk_float: /* empty parameter list */
2541 case tk_double: /* empty parameter list */
2543 case tk_boolean: /* empty parameter list */
2545 case tk_char: /* empty parameter list */
2547 case tk_octet: /* empty parameter list */
2549 case tk_any: /* empty parameter list */
2551 case tk_TypeCode: /* empty parameter list */
2553 case tk_Principal: /* empty parameter list */
2555 case tk_objref: /* complex parameter list */
2556 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2558 case tk_struct: /* complex parameter list */
2559 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2561 case tk_union: /* complex parameter list */
2562 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2564 case tk_enum: /* complex parameter list */
2565 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2568 case tk_string: /* simple parameter list */
2569 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2571 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2572 *offset-sizeof(u_octet4),4,u_octet4);
2576 case tk_sequence: /* complex parameter list */
2577 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2579 case tk_array: /* complex parameter list */
2580 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2582 case tk_alias: /* complex parameter list */
2583 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2585 case tk_except: /* complex parameter list */
2586 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2588 case tk_longlong: /* empty parameter list */
2590 case tk_ulonglong: /* empty parameter list */
2592 case tk_longdouble: /* empty parameter list */
2594 case tk_wchar: /* empty parameter list */
2596 case tk_wstring: /* simple parameter list */
2597 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2599 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2600 *offset-sizeof(u_octet4),4,u_octet4);
2604 case tk_fixed: /* simple parameter list */
2605 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2607 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2608 *offset-sizeof(u_octet2),2,u_octet2);
2611 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2613 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2614 *offset-sizeof(s_octet2),2,s_octet2);
2618 case tk_value: /* complex parameter list */
2619 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2621 case tk_value_box: /* complex parameter list */
2622 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2624 case tk_native: /* complex parameter list */
2625 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2627 case tk_abstract_interface: /* complex parameter list */
2628 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2631 g_warning("giop: Unknown TCKind %u \n", val);
2640 /* Copy a 4 octet sequence from the tvbuff
2641 * which represents an unsigned long value, and convert
2642 * it to an unsigned long vaule, taking into account byte order.
2643 * offset is first incremented so that it falls on a proper alignment
2644 * boundary for unsigned long values.
2645 * offset is then incremented by 4, to indicate the 4 octets which
2646 * have been processed.
2649 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2653 /* unsigned long values must be aligned on a 4 byte boundary */
2654 while( ( (*offset + boundary) % 4) != 0)
2657 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2658 tvb_get_letohl (tvb, *offset);
2665 /* Copy a 2 octet sequence from the tvbuff
2666 * which represents an unsigned short value, and convert
2667 * it to an unsigned short value, taking into account byte order.
2668 * offset is first incremented so that it falls on a proper alignment
2669 * boundary for unsigned short values.
2670 * offset is then incremented by 2, to indicate the 2 octets which
2671 * have been processed.
2674 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2678 /* unsigned short values must be aligned on a 2 byte boundary */
2679 while( ( (*offset + boundary) % 2) != 0)
2682 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2683 tvb_get_letohs (tvb, *offset);
2691 /* Copy a wchar from the tvbuff.
2692 * Caller of this function must remember to free the
2693 * array pointed to by seq.
2694 * This function also increments offset according to
2697 * For GIOP 1.1 read 2 octets and return size -2. The
2698 * negation means there is no size element in the packet
2699 * and therefore no size to add to the tree.
2701 * For GIOP 1.2 read size of wchar and the size
2702 * octets. size is returned as a gint8.
2704 * For both GIOP versions the wchar is returned
2705 * as a printable string.
2709 /* NOTE: This is very primitive in that it just reads
2710 * the wchar as a series of octets and returns them
2711 * to the user. No translation is attempted based on
2712 * byte orientation, nor on code set. I.e it only
2713 * really reads past the wchar and sets the offset
2717 /* The "decoding" is done according to CORBA chapter 15.
2718 * Wchar is not supported for GIOP 1.0.
2721 gint8 get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2726 /* CORBA chapter 15:
2727 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2728 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2729 * followed by the elements of the octet sequence representing
2730 * the encoded value of the wchar.
2733 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2734 slength = 2; /* set for GIOP 1.1 length in octets */
2736 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2737 slength = get_CDR_octet(tvb,offset);
2740 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2741 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2743 /* now turn octets (wchar) into something that can be printed by the user */
2744 *seq = make_printable_string(raw_wstring, slength);
2746 g_free(raw_wstring);
2749 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2750 if (header->GIOP_version.minor < 2)
2753 return slength; /* return length */
2758 /* Copy a wstring from the tvbuff.
2759 * Caller of this function must remember to free the
2760 * array pointed to by seq.
2761 * This function also increments offset, according to
2762 * wstring length. length is returned as guint32
2765 /* NOTE: This is very primitive in that it just reads
2766 * the wstring as a series of octets and returns them
2767 * to the user. No translation is attempted based on
2768 * byte orientation, nor on code set. I.e it only
2769 * really reads past the wstring and sets the offset
2773 /* The "decoding" is done according to CORBA chapter 15.
2774 * Wstring is not supported for GIOP 1.0.
2778 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2779 int boundary, MessageHeader * header) {
2784 /* CORBA chapter 15:
2785 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2786 * length and string are NUL terminated (length???).
2787 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2791 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2793 /* get length, same for all GIOP versions,
2794 * although for 1.2 CORBA doesnt say, so assume.
2796 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2800 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2801 slength = 5; /* better than core dumping during debug */
2805 if (header->GIOP_version.minor < 2) {
2807 (*offset)++; /* must step past \0 delimiter */
2809 /* assume length is number of characters and not octets, spec not clear */
2810 slength = slength * 2; /* length in octets is 2 * wstring length */
2814 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2816 /* now turn octets (wstring) into something that can be printed by the user */
2817 *seq = make_printable_string(raw_wstring, slength);
2819 g_free(raw_wstring);
2822 return slength; /* return length */
2829 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2831 * typedef short AddressingDisposition;
2832 * const short KeyAddr = 0;
2833 * const short ProfileAddr = 1;
2834 * const short ReferenceAddr = 2;
2835 * struct IORAddressingInfo {
2836 * unsigned long selected_profile_index;
2840 * union TargetAddress switch (AddressingDisposition) {
2841 * case KeyAddr: sequence <octet> object_key;
2842 * case ProfileAddr: IOP::TaggedProfile profile;
2843 * case ReferenceAddr: IORAddressingInfo ior;
2848 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2849 MessageHeader * header, gboolean stream_is_big_endian)
2851 guint16 discriminant;
2853 gchar *p_object_key;
2857 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2860 proto_tree_add_text (tree, tvb, *offset -2, 2,
2861 "TargetAddress Discriminant: %u", discriminant);
2864 switch (discriminant)
2866 case 0: /* KeyAddr */
2867 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2870 proto_tree_add_text (tree, tvb, *offset -4, 4,
2871 "KeyAddr (object key length): %u", len);
2876 get_CDR_octet_seq(tvb, &object_key, offset, len);
2877 p_object_key = make_printable_string( object_key, len );
2881 proto_tree_add_text (tree, tvb, *offset -len, len,
2882 "KeyAddr (object key): %s", p_object_key);
2884 g_free( p_object_key );
2885 g_free( object_key );
2888 case 1: /* ProfileAddr */
2889 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2890 stream_is_big_endian, NULL);
2892 case 2: /* ReferenceAddr */
2893 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2897 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2898 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2901 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2909 dissect_reply_body (tvbuff_t *tvb, u_int offset, packet_info *pinfo,
2910 proto_tree *tree, gboolean stream_is_big_endian,
2911 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2913 u_int sequence_length;
2914 gboolean exres = FALSE; /* result of trying explicit dissectors */
2915 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2918 * comp_req_list stuff
2921 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2925 switch (reply_status)
2927 case SYSTEM_EXCEPTION:
2929 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2932 case USER_EXCEPTION:
2934 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2938 proto_tree_add_text(tree, tvb, offset-4, 4,
2939 "Exception length: %u", sequence_length);
2941 if (sequence_length != 0)
2945 proto_tree_add_text(tree, tvb, offset, sequence_length,
2947 tvb_format_text(tvb, offset, sequence_length));
2951 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2953 /* read exception id from buffer and store in*/
2955 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2961 offset += sequence_length;
2967 * Now just fall through to the NO_EXCEPTION part
2968 * as this is common .
2976 /* lookup MFN in hash directly */
2978 mfn = get_mfn_from_fn(pinfo->fd->num);
2980 if (mfn == pinfo->fd->num)
2981 return; /* no matching frame number, what am I */
2983 /* get entry for this MFN */
2984 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2987 return; /* no matching entry */
2991 * If this packet is a REPLY to a RESOLVE(request)
2993 * TODO - make this lookup faster -- FS
2996 if (!strcmp(giop_op_resolve,entry->operation)) {
2997 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
3001 /* TODO -- Put stuff here for other "interesting operations" */
3005 * Call sub dissector.
3006 * First try an find a explicit sub_dissector, then if that
3007 * fails, try the heuristic method.
3012 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
3015 /* Only call heuristic if no explicit dixxector was found */
3018 try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
3024 case LOCATION_FORWARD:
3025 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3029 case LOCATION_FORWARD_PERM:
3030 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3034 case NEEDS_ADDRESSING_MODE: {
3036 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3038 proto_tree_add_text (tree, tvb, offset -2, 2,
3039 "AddressingDisposition: %u", addr_disp);
3047 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
3053 g_free(repoid); /* free resource */
3063 /* The format of the Reply Header for GIOP 1.0 and 1.1
3064 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
3066 struct ReplyHeader_1_0 {
3067 IOP::ServiceContextList service_context;
3068 unsigned long request_id;
3069 ReplyStatusType_1_0 reply_status;
3073 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3074 proto_tree * clnp_tree, MessageHeader * header,
3075 gboolean stream_is_big_endian) {
3079 guint32 reply_status;
3080 proto_tree *reply_tree = NULL;
3082 guint32 mfn; /* matching frame number */
3085 tf = proto_tree_add_text (tree, tvb, offset, -1,
3086 "General Inter-ORB Protocol Reply");
3087 if (reply_tree == NULL)
3089 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3095 * Decode IOP::ServiceContextList
3098 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3100 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3102 if (check_col(pinfo->cinfo, COL_INFO)) {
3103 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3107 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3108 "Request id: %u", request_id);
3111 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3113 if (check_col(pinfo->cinfo, COL_INFO)) {
3114 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3115 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3120 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3122 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3127 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3130 if (! pinfo->fd->flags.visited) {
3131 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3132 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3133 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3137 header->req_id = request_id; /* save for sub dissector */
3138 header->rep_status = reply_status; /* save for sub dissector */
3140 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3141 reply_status, header,tree);
3146 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3147 * and 1.1 header, only the fields have been rearranged. From Section
3148 * 15.4.3.1 of the CORBA 2.4 specification:
3150 * struct ReplyHeader_1_2 {
3151 * unsigned long request_id;
3152 * ReplyStatusType_1_2 reply_status;
3153 * IOP:ServiceContextList service_context;
3157 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3158 proto_tree * tree, proto_tree * clnp_tree,
3159 MessageHeader * header,
3160 gboolean stream_is_big_endian) {
3164 guint32 reply_status;
3165 proto_tree *reply_tree = NULL;
3167 guint32 mfn; /* matching frame number */
3170 tf = proto_tree_add_text (tree, tvb, offset, -1,
3171 "General Inter-ORB Protocol Reply");
3172 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3175 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3177 if (check_col(pinfo->cinfo, COL_INFO)) {
3178 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3182 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3183 "Request id: %u", request_id);
3186 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3188 if (check_col(pinfo->cinfo, COL_INFO)) {
3189 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3190 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3195 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3197 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3202 * Decode IOP::ServiceContextList
3205 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3208 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3211 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3214 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3217 if (! pinfo->fd->flags.visited) {
3218 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3219 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3220 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3225 * Add header to argument list so sub dissector can get header info.
3228 header->req_id = request_id; /* save for sub dissector */
3229 header->rep_status = reply_status; /* save for sub dissector */
3231 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3232 reply_status,header,tree);
3238 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3239 proto_tree * tree, proto_tree * clnp_tree,
3240 MessageHeader * header, gboolean stream_is_big_endian) {
3244 proto_tree *cancel_request_tree = NULL;
3248 tf = proto_tree_add_text (tree, tvb, offset, -1,
3249 "General Inter-ORB Protocol CancelRequest");
3250 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3253 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3255 if (check_col(pinfo->cinfo, COL_INFO)) {
3256 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3260 proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4,
3261 "Request id: %u", request_id);
3267 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3268 * in section 15.4.2.1 of the CORBA 2.4 specification.
3270 * struct RequestHeader{
3271 * IOP::ServiceContextList service_context;
3272 * unsigned long request_id;
3273 * boolean response_expected;
3274 * octet reserved[3]; // Only in GIOP 1.1
3275 * sequence<octet> object_key;
3277 * CORBA::OctetSeq requesting_principal;
3281 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3282 proto_tree * tree, proto_tree * clnp_tree,
3283 MessageHeader * header, gboolean stream_is_big_endian)
3289 guint32 objkey_len = 0; /* object key length */
3290 gchar *objkey = NULL; /* object key sequence */
3291 gchar *print_objkey; /* printable object key sequence */
3292 gboolean exres = FALSE; /* result of trying explicit dissectors */
3295 gchar *requesting_principal;
3296 gchar *print_requesting_principal;
3297 guint8 response_expected;
3299 proto_tree *request_tree = NULL;
3302 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3307 tf = proto_tree_add_text (tree, tvb, offset, -1,
3308 "General Inter-ORB Protocol Request");
3309 if (request_tree == NULL)
3311 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3320 * Decode IOP::ServiceContextList
3323 decode_ServiceContextList(tvb, pinfo, request_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3326 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3327 if (check_col(pinfo->cinfo, COL_INFO))
3329 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3333 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3334 "Request id: %u", request_id);
3337 response_expected = tvb_get_guint8( tvb, offset );
3339 if (check_col(pinfo->cinfo, COL_INFO))
3341 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3342 response_expected ? "two-way" : "one-way");
3346 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3347 "Response expected: %u", response_expected);
3350 if( header->GIOP_version.minor > 0)
3352 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3355 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3356 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3363 /* Length of object_key sequence */
3364 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3369 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3370 /**/ "Object Key length: %u", objkey_len);
3375 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3377 print_objkey = make_printable_string(objkey, objkey_len);
3381 proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
3382 /**/ "Object Key: %s", print_objkey);
3386 g_free( print_objkey );
3390 * Register a cleanup function in case on of our tvbuff accesses
3391 * throws an exception. We need to clean up objkey.
3393 CLEANUP_PUSH(g_free, objkey);
3395 /* length of operation string and string */
3396 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3399 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3400 /**/ "Operation length: %u", len);
3405 if (check_col(pinfo->cinfo, COL_INFO))
3407 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3411 proto_tree_add_text (request_tree, tvb, offset - len, len,
3412 /**/ "Operation: %s", operation);
3418 * Register a cleanup function in case on of our tvbuff accesses
3419 * throws an exception. We need to clean up operation.
3421 CLEANUP_PUSH(g_free, operation);
3423 /* length of requesting_principal string */
3424 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3427 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3428 /**/ "Requesting Principal Length: %u", len);
3433 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3435 print_requesting_principal = make_printable_string(requesting_principal, len);
3439 proto_tree_add_text (request_tree, tvb, offset - len, len,
3440 /**/ "Requesting Principal: %s", print_requesting_principal);
3444 g_free( print_requesting_principal );
3445 g_free( requesting_principal );
3450 * Save FN,reqid,and operation for later. Add sub_handle later.
3451 * But only if user is NOT clicking.
3454 if (! pinfo->fd->flags.visited)
3455 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3456 request_id,operation,NULL);
3460 * Call subdissector here before freeing "operation" and "key"
3461 * pass request_id also.
3462 * First try an find an explicit sub_dissector, then if that
3463 * fails, try the heuristic method.
3468 header->req_id = request_id; /* save for sub dissector */
3469 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3473 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3476 /* Only call heuristic if no explicit dissector was found */
3479 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3484 * We're done with operation, so we can call the cleanup handler to free
3485 * it, and then pop the cleanup handler.
3487 CLEANUP_CALL_AND_POP;
3490 * We're done with objkey, so we can call the cleanup handler to free
3491 * it, and then pop the cleanup handler.
3493 CLEANUP_CALL_AND_POP;
3497 /** The format of a GIOP 1.2 RequestHeader message is
3498 * (CORBA 2.4, sec. 15.4.2):
3500 * struct RequestHeader_1_2 {
3501 * unsigned long request_id;
3502 * octet response_flags;
3503 * octet reserved[3];
3504 * TargetAddress target;
3506 * IOP::ServiceContextList service_context;
3507 * // requesting_principal not in GIOP 1.2
3511 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3512 proto_tree * tree, proto_tree * clnp_tree,
3513 MessageHeader * header, gboolean stream_is_big_endian)
3518 guint8 response_flags;
3520 gchar *operation = NULL;
3521 proto_tree *request_tree = NULL;
3523 gboolean exres = FALSE; /* result of trying explicit dissectors */
3525 gchar *repoid = NULL;
3530 tf = proto_tree_add_text (tree, tvb, offset, -1,
3531 "General Inter-ORB Protocol Request");
3532 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3535 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3536 if (check_col(pinfo->cinfo, COL_INFO))
3538 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3542 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3543 "Request id: %u", request_id);
3546 response_flags = tvb_get_guint8( tvb, offset );
3550 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3551 "Response flags: %s (%u)",
3552 match_strval(response_flags, sync_scope),
3556 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3559 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3560 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3564 dissect_target_address(tvb, pinfo, &offset, request_tree, header, stream_is_big_endian);
3566 /* length of operation string */
3567 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3570 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3571 /**/ "Operation length: %u", len);
3576 if (check_col(pinfo->cinfo, COL_INFO))
3578 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3582 proto_tree_add_text (request_tree, tvb, offset - len, len,
3583 /**/ "Operation: %s", operation);
3590 * Register a cleanup function in case on of our tvbuff accesses
3591 * throws an exception. We need to clean up operation.
3593 CLEANUP_PUSH(g_free, operation);
3596 * Decode IOP::ServiceContextList
3599 decode_ServiceContextList(tvb, pinfo, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3602 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3603 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3604 * GIOP octet stream start.
3607 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3610 * Save FN,reqid,and operation for later. Add sub_handle later.
3611 * But only if user is NOT clicking.
3614 if (! pinfo->fd->flags.visited)
3615 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3616 request_id,operation,NULL);
3620 * Call sub dissector.
3621 * First try an find a explicit sub_dissector, then if that
3622 * fails, try the heuristic method.
3627 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3630 /* Only call heuristic if no explicit dissector was found */
3633 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3638 * We're done with operation, so we can call the cleanup handler to free
3639 * it, and then pop the cleanup handler.
3641 CLEANUP_CALL_AND_POP;
3645 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3646 proto_tree * tree, MessageHeader * header,
3647 gboolean stream_is_big_endian)
3653 gchar *p_object_key;
3654 proto_tree *locate_request_tree = NULL;
3659 tf = proto_tree_add_text (tree, tvb, offset, -1,
3660 "General Inter-ORB Locate Request");
3661 if (locate_request_tree == NULL)
3663 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3668 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3669 if (check_col(pinfo->cinfo, COL_INFO))
3671 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3673 if (locate_request_tree)
3675 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3676 "Request id: %u", request_id);
3679 if(header->GIOP_version.minor < 2)
3681 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3682 if (locate_request_tree)
3684 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3685 "Object Key length: %u", len);
3689 get_CDR_octet_seq(tvb, &object_key, &offset, len);
3691 p_object_key = make_printable_string(object_key, len);
3693 if(locate_request_tree)
3696 proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
3697 "Object Key: %s", p_object_key);
3700 g_free(p_object_key);
3704 else /* GIOP 1.2 and higher */
3706 dissect_target_address(tvb, pinfo, &offset, locate_request_tree, header,
3707 stream_is_big_endian);
3713 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3714 proto_tree * tree, MessageHeader * header,
3715 gboolean stream_is_big_endian)
3719 guint32 locate_status;
3722 proto_tree *locate_reply_tree = NULL;
3727 tf = proto_tree_add_text (tree, tvb, offset, -1,
3728 "General Inter-ORB Locate Reply");
3729 if (locate_reply_tree == NULL)
3731 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3736 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3737 if (check_col(pinfo->cinfo, COL_INFO))
3739 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3741 if (locate_reply_tree)
3743 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3744 "Request id: %u", request_id);
3747 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3748 if (locate_reply_tree)
3750 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3751 "Locate status: %s",
3752 match_strval(locate_status, giop_locate_status_types)
3756 /* Decode the LocateReply body.
3758 * For GIOP 1.0 and 1.1 body immediately follows header.
3759 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3763 if (header->GIOP_version.minor > 1) {
3764 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3768 switch(locate_status) {
3769 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3770 case OBJECT_FORWARD_PERM:
3771 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3773 case LOC_SYSTEM_EXCEPTION:
3774 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3776 case LOC_NEEDS_ADDRESSING_MODE:
3777 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3778 if(locate_reply_tree) {
3779 proto_tree_add_text (tree, tvb, offset -2, 2,
3780 "AddressingDisposition: %u", addr_disp);
3783 default: /* others have no reply body */
3790 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3791 MessageHeader * header, gboolean stream_is_big_endian)
3795 proto_tree *fragment_tree = NULL;
3800 tf = proto_tree_add_text (tree, tvb, offset, -1,
3801 "General Inter-ORB Fragment");
3802 if (fragment_tree == NULL)
3804 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3809 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3810 if (check_col(pinfo->cinfo, COL_INFO))
3812 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3816 proto_tree_add_text (fragment_tree, tvb, offset-4, 4,
3817 "Request id: %u", request_id);
3823 /* Main entry point */
3825 gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3827 MessageHeader header;
3828 tvbuff_t *giop_header_tvb;
3829 tvbuff_t *payload_tvb;
3831 proto_tree *clnp_tree = NULL;
3834 u_int minor_version;
3835 gboolean stream_is_big_endian;
3841 giop_dump_collection(cd_module_hash);
3842 giop_dump_collection(cd_objkey_hash);
3843 giop_dump_collection(cd_heuristic_users);
3844 giop_dump_collection(cd_complete_reply_hash);
3845 giop_dump_collection(cd_complete_request_list);
3848 header.exception_id = NULL;
3850 /* check magic number and version */
3853 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
3855 if (tvb_length_remaining(tvb, 0) < GIOP_HEADER_SIZE)
3857 /* Not enough data captured to hold the GIOP header; don't try
3858 to interpret it as GIOP. */
3862 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3863 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3866 * because I have added extra elements in MessageHeader struct
3867 * for sub dissectors. -- FS
3870 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3872 if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
3874 /* Not a GIOP message. */
3879 if (check_col (pinfo->cinfo, COL_PROTOCOL))
3881 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3884 if (header.GIOP_version.major != GIOP_MAJOR ||
3885 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3887 /* Bad version number; should we note that and dissect the rest
3888 as data, or should we return FALSE on the theory that it
3889 might have been some other packet that happened to begin with
3890 "GIOP"? We shouldn't do *both*, so we return TRUE, for now.
3891 If we should return FALSE, we should do so *without* setting
3892 the "Info" column, *without* setting the "Protocol" column,
3893 and *without* adding anything to the protocol tree. */
3895 if (check_col (pinfo->cinfo, COL_INFO))
3897 col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3898 header.GIOP_version.major, header.GIOP_version.minor);
3902 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3903 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3904 proto_tree_add_text (clnp_tree, giop_header_tvb, 0, -1,
3905 "Version %u.%u not supported",
3906 header.GIOP_version.major,
3907 header.GIOP_version.minor);
3909 call_dissector(data_handle,payload_tvb, pinfo, tree);
3913 if (check_col (pinfo->cinfo, COL_INFO))
3915 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3916 header.GIOP_version.major, header.GIOP_version.minor,
3917 val_to_str(header.message_type, giop_message_types,
3918 "Unknown message type (0x%02x)"));
3921 stream_is_big_endian = is_big_endian (&header);
3923 if (stream_is_big_endian)
3924 message_size = pntohl (&header.message_size);
3926 message_size = pletohl (&header.message_size);
3930 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, 12, FALSE);
3931 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3932 proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3933 "Magic number: %s", GIOP_MAGIC);
3934 proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3936 header.GIOP_version.major,
3937 header.GIOP_version.minor);
3938 switch (minor_version)
3942 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3943 "Flags: 0x%02x (%s %s)",
3945 (stream_is_big_endian) ? "big-endian" : "little-endian",
3946 (header.flags & 0x02) ? " fragment" : "");
3949 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3950 "Byte ordering: %s-endian",
3951 (stream_is_big_endian) ? "big" : "little");
3955 } /* minor_version */
3957 proto_tree_add_uint_format (clnp_tree,
3958 hf_giop_message_type,
3959 giop_header_tvb, 7, 1,
3960 header.message_type,
3961 "Message type: %s", match_strval(header.message_type, giop_message_types));
3963 proto_tree_add_uint (clnp_tree,
3964 hf_giop_message_size,
3965 giop_header_tvb, 8, 4, message_size);
3970 if (check_col (pinfo->cinfo, COL_INFO))
3972 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3973 header.GIOP_version.major, header.GIOP_version.minor,
3974 match_strval(header.message_type, giop_message_types));
3978 switch (header.message_type)
3982 if(header.GIOP_version.minor < 2)
3984 dissect_giop_request_1_1 (payload_tvb, pinfo, tree, clnp_tree,
3985 &header, stream_is_big_endian);
3989 dissect_giop_request_1_2 (payload_tvb, pinfo, tree, clnp_tree,
3990 &header, stream_is_big_endian);
3997 if(header.GIOP_version.minor < 2)
3999 dissect_giop_reply (payload_tvb, pinfo, tree, clnp_tree, &header,
4000 stream_is_big_endian);
4004 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree, clnp_tree,
4005 &header, stream_is_big_endian);
4009 dissect_giop_cancel_request(payload_tvb, pinfo, tree, clnp_tree,
4010 &header, stream_is_big_endian);
4013 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
4014 stream_is_big_endian);
4017 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
4018 stream_is_big_endian);
4021 dissect_giop_fragment(payload_tvb, pinfo, tree, &header,
4022 stream_is_big_endian);
4027 } /* switch message_type */
4031 * XXX - we should catch exceptions here, so that we can free
4032 * this if an exception is thrown.
4033 * We'd then have to forward the exception.
4035 if (header.exception_id != NULL)
4036 g_free(header.exception_id);
4042 proto_register_giop (void)
4044 static hf_register_info hf[] = {
4045 { &hf_giop_message_type,
4046 { "Message type", "giop.type",
4047 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4050 { &hf_giop_message_size,
4051 { "Message size", "giop.len",
4052 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4056 { "Repository ID", "giop.repoid",
4057 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4060 { &hf_giop_string_length,
4061 { "String Length", "giop.strlen",
4062 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4065 { &hf_giop_sequence_length,
4066 { "Sequence Length", "giop.seqlen",
4067 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4070 { &hf_giop_profile_id,
4071 { "Profile ID", "giop.profid",
4072 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
4077 { "IOR::type_id", "giop.typeid",
4078 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4081 { &hf_giop_iiop_v_maj,
4082 { "IIOP Major Version", "giop.iiop_vmaj",
4083 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4086 { &hf_giop_iiop_v_min,
4087 { "IIOP Minor Version", "giop.iiop_vmin",
4088 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4091 { &hf_giop_endianess,
4092 { "Endianess", "giop.endianess",
4093 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4096 { &hf_giop_IIOP_tag,
4097 { "IIOP Component TAG", "giop.iioptag",
4098 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4102 { "IOR Profile TAG", "giop.iortag",
4103 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4107 { "TypeCode enum", "giop.TCKind",
4108 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4111 { &hf_giop_typecode_count,
4112 { "TypeCode count", "giop.tccount",
4113 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4116 { &hf_giop_typecode_default_used,
4117 { "default_used", "giop.tcdefault_used",
4118 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4121 { &hf_giop_typecode_digits,
4122 { "Digits", "giop.tcdigits",
4123 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4127 { &hf_giop_typecode_length,
4128 { "Length", "giop.tclength",
4129 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4132 { &hf_giop_typecode_max_length,
4133 { "Maximum length", "giop.tcmaxlen",
4134 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4137 { &hf_giop_typecode_member_name,
4138 { "TypeCode member name", "giop.tcmemname",
4139 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4142 { &hf_giop_typecode_name,
4143 { "TypeCode name", "giop.tcname",
4144 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4147 { &hf_giop_typecode_scale,
4148 { "Scale", "giop.tcscale",
4149 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4152 { &hf_giop_typecode_ValueModifier,
4153 { "ValueModifier", "giop.tcValueModifier",
4154 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4157 { &hf_giop_typecode_Visibility,
4158 { "Visibility", "giop.tcVisibility",
4159 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4164 { &hf_giop_type_boolean,
4165 { "TypeCode boolean data", "giop.tcboolean",
4166 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4169 { &hf_giop_type_char,
4170 { "TypeCode char data", "giop.tcchar",
4171 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4174 { &hf_giop_type_double,
4175 { "TypeCode double data", "giop.tcdouble",
4176 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4179 { &hf_giop_type_enum,
4180 { "TypeCode enum data", "giop.tcenumdata",
4181 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4185 * float as double ?? -- FIX
4188 { &hf_giop_type_float,
4189 { "TypeCode float data", "giop.tcfloat",
4190 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4193 { &hf_giop_type_long,
4194 { "TypeCode long data", "giop.tclongdata",
4195 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4198 { &hf_giop_type_octet,
4199 { "TypeCode octet data", "giop.tcoctet",
4200 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4203 { &hf_giop_type_short,
4204 { "TypeCode short data", "giop.tcshortdata",
4205 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4208 { &hf_giop_type_string,
4209 { "TypeCode string data", "giop.tcstring",
4210 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4213 { &hf_giop_type_ulong,
4214 { "TypeCode ulong data", "giop.tculongdata",
4215 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4218 { &hf_giop_type_ushort,
4219 { "TypeCode ushort data", "giop.tcushortdata",
4220 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4224 * IIOP Module - Chapter 15.10.2
4227 { &hf_giop_iiop_host,
4228 { "IIOP::Profile_host", "giop.iiop.host",
4229 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4233 { &hf_giop_iiop_port,
4234 { "IIOP::Profile_port", "giop.iiop.port",
4235 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4240 * IIOP ServiceContext
4243 { &hf_giop_iop_vscid,
4244 { "VSCID", "giop.iiop.vscid",
4245 FT_UINT32, BASE_HEX, NULL, 0xfffff000, "", HFILL }
4249 { &hf_giop_iop_scid,
4250 { "SCID", "giop.iiop.scid",
4251 FT_UINT32, BASE_HEX, NULL, 0x00000fff, "", HFILL }
4258 static gint *ett[] = {
4262 &ett_giop_cancel_request,
4263 &ett_giop_locate_request,
4264 &ett_giop_locate_reply,
4270 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4272 proto_register_field_array (proto_giop, hf, array_length (hf));
4273 proto_register_subtree_array (ett, array_length (ett));
4276 /* register init routine */
4278 register_init_routine( &giop_init); /* any init stuff */
4281 * Init the giop user module hash tables here, as giop users
4282 * will populate it via register_giop_user_module BEFORE my
4283 * own giop_init() is called.
4286 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4288 giop_module_keys = g_mem_chunk_new("giop_module_keys",
4289 sizeof(struct giop_module_key),
4290 giop_module_init_count * sizeof(struct giop_module_key),
4293 giop_module_vals = g_mem_chunk_new("giop_module_vals",
4294 sizeof(struct giop_module_val),
4295 giop_module_init_count * sizeof(struct giop_module_val),
4302 void proto_reg_handoff_giop (void) {
4303 data_handle = find_dissector("data");
4304 heur_dissector_add("tcp", dissect_giop, proto_giop);
4305 /* Support DIOP (GIOP/UDP) */
4306 heur_dissector_add("udp", dissect_giop, proto_giop);
4315 * Ref Corba v2.4.2 Chapter 13
4323 typedef unsigned long ProfileId;
4325 const ProfileId TAG_INTERNET_IOP = 0;
4326 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4328 struct TaggedProfile {
4330 sequence <octet> profile_data;
4335 sequence <TaggedProfile> profiles;
4338 typedef unsigned long ComponentId;
4340 struct TaggedComponent {
4342 sequence <octet> component_data;
4345 typedef sequence <TaggedComponent> MultipleComponentProfile;
4351 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4352 guint32 boundary, gboolean stream_is_big_endian) {
4355 guint32 seqlen_p; /* sequence length of profiles */
4358 proto_tree *tree = NULL; /* IOR tree */
4361 gchar *repobuf; /* for repository ID */
4365 /* create a subtree */
4368 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
4369 tree = proto_item_add_subtree (tf, ett_giop_ior);
4373 /* Get type_id == Repository ID */
4375 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4378 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4379 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4381 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4382 *offset-u_octet4,u_octet4,repobuf);
4387 * Register a cleanup function in case on of our tvbuff accesses
4388 * throws an exception. We need to clean up repobuf.
4389 * We can't free it yet, as we must wait until we have the object
4390 * key, as we have to add both to the hash table.
4392 CLEANUP_PUSH(g_free, repobuf);
4394 /* Now get a sequence of profiles */
4395 /* Get sequence length (number of elements) */
4397 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4399 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4400 *offset-sizeof(seqlen_p),4,seqlen_p);
4404 /* fetch all TaggedProfiles in this sequence */
4406 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4407 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4411 * We're done with repobuf, so we can call the cleanup handler to free
4412 * it, and then pop the cleanup handler.
4414 CLEANUP_CALL_AND_POP;
4418 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4419 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4421 guint32 seqlen_pd; /* sequence length of profile data */
4423 guint32 pidtag; /* profile ID TAG */
4425 gchar *profile_data; /* profile_data pointer */
4426 gchar *p_profile_data; /* printable profile_data pointer */
4428 guint32 new_boundary; /* for encapsulations encountered */
4429 gboolean new_big_endianess; /* for encapsulations encountered */
4431 /* Get ProfileId tag */
4433 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4436 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4437 *offset-sizeof(pidtag),4,pidtag);
4440 /* get sequence length, new endianness and boundary for encapsulation */
4442 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4443 stream_is_big_endian, boundary,
4444 &new_big_endianess, &new_boundary);
4446 /* return if zero length sequence */
4453 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4454 * decode it, otherwise just dump the octet sequence
4456 * also, store IOR in our objectkey hash
4458 * TODO - handle other TAGS
4462 case IOP_TAG_INTERNET_IOP:
4464 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4469 /* fetch all octets in this sequence , but skip endianess */
4471 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4473 /* Make a printable string */
4475 p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4478 proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4479 "Profile Data: %s", p_profile_data);
4482 g_free(p_profile_data);
4484 g_free(profile_data);
4495 * Decode IIOP IOR Profile
4496 * Ref Chap 15.7.2 in Corba Spec
4500 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4501 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4502 gboolean store_flag) {
4504 guint32 i; /* loop index */
4506 guint8 v_major,v_minor; /* IIOP sersion */
4508 guint32 u_octet4; /* u long */
4509 guint16 u_octet2; /* u short */
4510 guint32 seqlen; /* generic sequence length */
4511 guint32 seqlen1; /* generic sequence length */
4512 gchar *objkey; /* object key pointer */
4513 gchar *p_chars; /* printable characters pointer */
4516 /* Get major/minor version */
4518 v_major = get_CDR_octet(tvb,offset);
4519 v_minor = get_CDR_octet(tvb,offset);
4523 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4524 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4525 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4526 *offset-sizeof(v_minor),1,v_minor );
4532 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4535 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4536 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4538 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4539 *offset-u_octet4,u_octet4,buf);
4543 g_free(buf); /* dont forget */
4547 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4550 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4551 *offset-sizeof(u_octet2),2,u_octet2);
4555 /* Object Key - sequence<octet> object_key */
4557 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4560 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4561 *offset-sizeof(seqlen),4,seqlen);
4565 /* fetch all octets in this sequence */
4566 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4569 * Now we may have the Repository ID from earlier, as well
4570 * as the object key sequence and lengh. So lets store them in
4571 * our objectkey hash and free buffers.
4573 * But only insert if user is not clicking and repo id not NULL.
4579 if(!pinfo->fd->flags.visited)
4580 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4585 * No pinfo, but store anyway if flag set. eg: IOR read from file
4589 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4593 /* Make a printable string */
4595 p_chars = make_printable_string( objkey, seqlen );
4598 proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
4599 "Object Key: %s", p_chars);
4607 * Now see if if its v1.1 or 1.2, as they can contain
4608 * extra sequence of IOP::TaggedComponents
4621 /* sequence of IOP::TaggedComponents */
4622 /* Ref Chap 13 in Corba Spec */
4624 /* get sequence length */
4625 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4628 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4629 *offset-sizeof(seqlen),4,seqlen);
4632 for (i=0; i< seqlen; i++) {
4634 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4636 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4637 *offset-sizeof(u_octet4),4,u_octet4);
4640 /* get component_data */
4641 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4643 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4644 *offset-sizeof(seqlen1),4,seqlen1);
4648 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4651 /* Make a printable string of data */
4653 p_chars = make_printable_string(buf, seqlen1);
4655 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4656 "component_data: %s", p_chars);
4670 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4678 * Service Contexts Begin
4686 void dissect_SID_BI_DIR_IIOP(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4687 MessageHeader *header, gchar *operation, guint32 boundary) {
4697 * Service Contexts End
4709 * typedef unsigned long ServiceID;
4711 * struct ServiceContext {
4712 * ServiceID context_id;
4713 * sequence <octet> context_data;
4715 * typedef sequence <ServiceContext> ServiceContextList;
4718 * Note: Spec says context_data is an encapsulation.
4725 void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4726 gboolean stream_is_be, guint32 boundary) {
4728 guint32 seqlen; /* sequence length */
4729 guint32 seqlen_cd; /* sequence length, context_data */
4731 proto_tree *tree = NULL; /* ServiceContext tree */
4735 gchar *context_data;
4736 gchar *p_context_data;
4739 guint32 vscid; /* Vendor Service context id */
4742 /* create a subtree */
4745 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "ServiceContextList");
4746 tree = proto_item_add_subtree (tf, ett_giop_scl);
4749 /* Get sequence length (number of elements) */
4751 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4753 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4754 *offset-sizeof(seqlen),4,seqlen);
4757 /* return if zero length sequence */
4762 /* Loop for all ServiceContext's */
4764 for (i=0; i<seqlen; i++) {
4766 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4768 proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4769 *offset-sizeof(context_id),4,context_id);
4771 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4772 *offset-sizeof(context_id),4,context_id);
4776 vscid = context_id && 0xfffff000; /* vendor info, top 20 bits */
4777 scid = context_id && 0x00000fff; /* standard service info, lower 12 bits */
4780 #if CONTEXT_DATA_IS_ENCAPSULATED
4782 /* get sequence length, new endianness and boundary for encapsulation */
4784 seqlen_cd = get_CDR_encap_info(tvb, tree, offset,
4785 stream_is_be, boundary,
4786 &new_big_endianess, &new_boundary);
4790 /* get sequence length, and NO encapsulation */
4792 seqlen_cd = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4796 /* return if zero length sequence */
4802 * Now decode sequence according to vendor ServiceId, but I dont
4803 * have that yet, so just dump it as data.
4806 /* fetch all octets in this sequence */
4808 get_CDR_octet_seq(tvb, &context_data, offset, seqlen_cd);
4810 /* Make a printable string */
4812 p_context_data = make_printable_string( context_data, seqlen_cd );
4815 proto_tree_add_text (tree, tvb, *offset - seqlen_cd , seqlen_cd,
4816 "context_data: %s", p_context_data);
4819 g_free(context_data);
4820 g_free(p_context_data);
4825 return; /* for now, fix later */
4830 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
4833 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
4834 gboolean stream_is_big_endian,
4837 guint32 length; /* string length */
4838 guint32 minor_code_value;
4839 guint32 completion_status;
4841 gchar *buf; /* pointer to string buffer */
4843 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
4846 proto_tree_add_text(tree, tvb, *offset-4, 4,
4847 "Exception length: %u", length);
4849 proto_tree_add_text(tree, tvb, *offset - length, length,
4850 "Exception id: %s", buf );
4855 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4856 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4859 proto_tree_add_text(tree, tvb, *offset-8, 4,
4860 "Minor code value: %u", minor_code_value);
4861 proto_tree_add_text(tree, tvb, *offset-4, 4,
4862 "Completion Status: %u", completion_status);
4868 * Helper functions for dissecting TypeCodes
4870 * These functions decode the complex parameter lists
4871 * of TypeCodes as defined in the CORBA spec chapter 15.
4874 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4875 gboolean stream_is_big_endian, guint32 boundary,
4876 MessageHeader * header) {
4878 guint32 new_boundary; /* new boundary for encapsulation */
4879 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4881 guint32 seqlen; /* sequence length */
4883 /* get sequence length, new endianness and boundary for encapsulation */
4884 seqlen = get_CDR_encap_info(tvb, tree, offset,
4885 stream_is_big_endian, boundary,
4886 &new_stream_is_big_endian, &new_boundary);
4888 /* get repository ID */
4889 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4893 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4894 hf_giop_typecode_name);
4899 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4900 gboolean stream_is_big_endian, guint32 boundary,
4901 MessageHeader * header ) {
4903 guint32 new_boundary; /* new boundary for encapsulation */
4904 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4906 guint32 count; /* parameter count (of tuples) */
4907 guint32 seqlen; /* sequence length */
4908 guint32 i; /* loop index */
4910 /* get sequence lengt,h new endianness and boundary for encapsulation */
4911 seqlen = get_CDR_encap_info(tvb, tree, offset,
4912 stream_is_big_endian, boundary,
4913 &new_stream_is_big_endian, &new_boundary);
4915 /* get repository ID */
4916 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4920 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4921 hf_giop_typecode_name);
4923 /* get count of tuples */
4924 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4926 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4927 *offset-sizeof(count),4,count);
4930 /* get all tuples */
4931 for (i=0; i< count; i++) {
4932 /* get member name */
4933 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4934 hf_giop_typecode_member_name);
4936 /* get member type */
4937 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4943 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4944 gboolean stream_is_big_endian, guint32 boundary,
4945 MessageHeader * header) {
4947 guint32 new_boundary; /* new boundary for encapsulation */
4948 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4950 guint32 TCKind; /* TypeCode */
4951 gint32 s_octet4; /* signed int32 */
4953 guint32 count; /* parameter count (of tuples) */
4954 guint32 seqlen; /* sequence length */
4955 guint32 i; /* loop index */
4957 /* get sequence legnth, new endianness and boundary for encapsulation */
4958 seqlen = get_CDR_encap_info(tvb, tree, offset,
4959 stream_is_big_endian, boundary,
4960 &new_stream_is_big_endian, &new_boundary);
4962 /* get repository ID */
4963 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4967 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4968 hf_giop_typecode_name);
4970 /* get discriminant type */
4971 TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4973 /* get default used */
4974 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
4976 proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
4977 *offset-sizeof(s_octet4),4,s_octet4);
4979 /* get count of tuples */
4980 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4982 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4983 *offset-sizeof(count),4,count);
4986 /* get all tuples */
4987 for (i=0; i< count; i++) {
4988 /* get label value, based on TCKind above */
4989 dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
4991 /* get member name */
4992 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4993 hf_giop_typecode_member_name);
4995 /* get member type */
4996 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5002 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5003 gboolean stream_is_big_endian, guint32 boundary,
5004 MessageHeader * header) {
5006 guint32 new_boundary; /* new boundary for encapsulation */
5007 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5009 guint32 count; /* parameter count (of tuples) */
5010 guint32 seqlen; /* sequence length */
5011 guint32 i; /* loop index */
5013 /* get sequence length, new endianness and boundary for encapsulation */
5014 seqlen = get_CDR_encap_info(tvb, tree, offset,
5015 stream_is_big_endian, boundary,
5016 &new_stream_is_big_endian, &new_boundary);
5018 /* get repository ID */
5019 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5023 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5024 hf_giop_typecode_name);
5026 /* get count of tuples */
5027 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5029 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5030 *offset-sizeof(count),4,count);
5033 /* get all tuples */
5034 for (i=0; i< count; i++) {
5035 /* get member name */
5036 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5037 hf_giop_typecode_member_name);
5043 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5044 gboolean stream_is_big_endian, guint32 boundary,
5045 MessageHeader * header) {
5047 guint32 new_boundary; /* new boundary for encapsulation */
5048 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5050 guint32 u_octet4; /* unsigned int32 */
5052 guint32 seqlen; /* sequence length */
5054 /* get sequence length, new endianness and boundary for encapsulation */
5055 seqlen = get_CDR_encap_info(tvb, tree, offset,
5056 stream_is_big_endian, boundary,
5057 &new_stream_is_big_endian, &new_boundary);
5059 /* get element type */
5060 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5062 /* get max length */
5063 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5065 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
5066 *offset-sizeof(u_octet4),4,u_octet4);
5071 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5072 gboolean stream_is_big_endian, guint32 boundary,
5073 MessageHeader * header) {
5075 guint32 new_boundary; /* new boundary for encapsulation */
5076 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5078 guint32 u_octet4; /* unsigned int32 */
5080 guint32 seqlen; /* sequence length */
5082 /* get sequence length, new endianness and boundary for encapsulation */
5083 seqlen = get_CDR_encap_info(tvb, tree, offset,
5084 stream_is_big_endian, boundary,
5085 &new_stream_is_big_endian, &new_boundary);
5087 /* get element type */
5088 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5091 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5093 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5094 *offset-sizeof(u_octet4),4,u_octet4);
5099 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5100 gboolean stream_is_big_endian, guint32 boundary,
5101 MessageHeader * header) {
5103 guint32 new_boundary; /* new boundary for encapsulation */
5104 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5106 guint32 seqlen; /* sequence length */
5108 /* get sequence legnth, new endianness and boundary for encapsulation */
5109 seqlen = get_CDR_encap_info(tvb, tree, offset,
5110 stream_is_big_endian, boundary,
5111 &new_stream_is_big_endian, &new_boundary);
5113 /* get repository ID */
5114 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5118 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5119 hf_giop_typecode_name);
5121 /* get ??? (noname) TypeCode */
5122 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5127 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5128 gboolean stream_is_big_endian, guint32 boundary,
5129 MessageHeader * header) {
5131 guint32 new_boundary; /* new boundary for encapsulation */
5132 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5134 guint32 count; /* parameter count (of tuples) */
5135 guint32 seqlen; /* sequence length */
5136 guint32 i; /* loop index */
5138 /* get sequence length, new endianness and boundary for encapsulation */
5139 seqlen = get_CDR_encap_info(tvb, tree, offset,
5140 stream_is_big_endian, boundary,
5141 &new_stream_is_big_endian, &new_boundary);
5143 /* get repository ID */
5144 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5148 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5149 hf_giop_typecode_name);
5151 /* get count of tuples */
5152 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5154 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5155 *offset-sizeof(count),4,count);
5158 /* get all tuples */
5159 for (i=0; i< count; i++) {
5160 /* get member name */
5161 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5162 hf_giop_typecode_member_name);
5164 /* get member type */
5165 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5171 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5172 gboolean stream_is_big_endian, guint32 boundary,
5173 MessageHeader * header) {
5175 guint32 new_boundary; /* new boundary for encapsulation */
5176 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5178 gint16 s_octet2; /* signed int16 */
5180 guint32 count; /* parameter count (of tuples) */
5181 guint32 seqlen; /* sequence length */
5182 guint32 i; /* loop index */
5184 /* get sequence length, new endianness and boundary for encapsulation */
5185 seqlen = get_CDR_encap_info(tvb, tree, offset,
5186 stream_is_big_endian, boundary,
5187 &new_stream_is_big_endian, &new_boundary);
5189 /* get repository ID */
5190 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5194 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5195 hf_giop_typecode_name);
5197 /* get ValueModifier */
5198 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5200 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5201 *offset-sizeof(s_octet2),2,s_octet2);
5204 /* get conrete base */
5205 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5207 /* get count of tuples */
5208 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5210 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5211 *offset-sizeof(count),4,count);
5214 /* get all tuples */
5215 for (i=0; i< count; i++) {
5216 /* get member name */
5217 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5218 hf_giop_typecode_member_name);
5220 /* get member type */
5221 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5223 /* get Visibility */
5224 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5226 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5227 *offset-sizeof(s_octet2),2,s_octet2);
5234 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5235 gboolean stream_is_big_endian, guint32 boundary,
5236 MessageHeader * header) {
5238 guint32 new_boundary; /* new boundary for encapsulation */
5239 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5241 guint32 seqlen; /* sequence length */
5243 /* get sequence length, new endianness and boundary for encapsulation */
5244 seqlen = get_CDR_encap_info(tvb, tree, offset,
5245 stream_is_big_endian, boundary,
5246 &new_stream_is_big_endian, &new_boundary);
5248 /* get repository ID */
5249 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5253 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5254 hf_giop_typecode_name);
5256 /* get ??? (noname) TypeCode */
5257 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5261 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5262 gboolean stream_is_big_endian, guint32 boundary,
5263 MessageHeader * header) {
5265 guint32 new_boundary; /* new boundary for encapsulation */
5266 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5268 guint32 seqlen; /* sequence length */
5270 /* get sequence length, new endianness and boundary for encapsulation */
5271 seqlen = get_CDR_encap_info(tvb, tree, offset,
5272 stream_is_big_endian, boundary,
5273 &new_stream_is_big_endian, &new_boundary);
5275 /* get repository ID */
5276 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5280 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5281 hf_giop_typecode_name);
5286 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5287 gboolean stream_is_big_endian, guint32 boundary,
5288 MessageHeader * header) {
5290 guint32 new_boundary; /* new boundary for encapsulation */
5291 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5293 guint32 seqlen; /* sequence length */
5295 /* get sequence length, new endianness and boundary for encapsulation */
5296 seqlen = get_CDR_encap_info(tvb, tree, offset,
5297 stream_is_big_endian, boundary,
5298 &new_stream_is_big_endian, &new_boundary);
5300 /* get repository ID */
5301 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5305 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5306 hf_giop_typecode_name);
5310 /* Typecode parameter lists are encoded as encapsulations and
5311 * this function gets the encapsulation information; see
5312 * CORBA spec chapter 15
5315 * Renamed to get_CDR_encap_info() for any encapsulation
5316 * we come across, useful helper function
5318 * Also, should return immediately if seqlen == 0.
5319 * ie: Forget about trying to grab endianess for
5320 * zero length sequence.
5322 * Caller must always check seqlen == 0, and not assume its value
5325 * Note: there seemed to be considerable confusion in corba
5326 * circles as to the correct interpretation of encapsulations,
5327 * and zero length sequences etc, but this is our best bet at the
5334 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5335 gboolean old_stream_is_big_endian, guint32 old_boundary,
5336 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5338 guint32 seqlen; /* sequence length */
5339 guint8 giop_endianess;
5341 /* Get sequence length of parameter list */
5342 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5344 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5345 *offset-sizeof(seqlen),4,seqlen);
5351 * seqlen == 0, implies no endianess and no data
5352 * so just return. Populate new_boundary_ptr and
5353 * new_stream_is_big_endian_ptr with current (old)
5354 * values, just to keep everyone happy. -- FS
5360 *new_boundary_ptr = old_boundary;
5361 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5367 /* Start of encapsulation of parameter list */
5368 *new_boundary_ptr = *offset; /* remember */
5369 giop_endianess = get_CDR_octet(tvb,offset);
5371 *new_stream_is_big_endian_ptr = ! giop_endianess;
5374 * Glib: typedef gint gboolean;
5375 * ie: It is not a guint8, so cannot use sizeof to correctly
5381 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5382 *offset-1,1,giop_endianess);
5392 * gets a TypeCode complex string parameter and
5393 * displays it in the relevant tree.
5396 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5397 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5399 guint32 u_octet4; /* unsigned int32 */
5400 gchar *buf; /* ptr to string buffer */
5403 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5406 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5407 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5409 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5413 g_free(buf); /* dont forget */
5418 * For a given data type, given by a TypeCode gets the associated data
5419 * and displays it in the relevant tree.
5422 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5423 gboolean stream_is_big_endian, guint32 boundary,
5424 MessageHeader * header, guint32 data_type ) {
5426 gboolean my_boolean; /* boolean */
5428 gint8 s_octet1; /* signed int8 */
5429 guint8 u_octet1; /* unsigned int8 */
5431 gint16 s_octet2; /* signed int16 */
5432 guint16 u_octet2; /* unsigned int16 */
5434 gint32 s_octet4; /* signed int32 */
5435 guint32 u_octet4; /* unsigned int32 */
5437 gdouble my_double; /* double */
5438 gfloat my_float; /* float */
5440 gchar *buf = NULL; /* ptr to string buffer */
5442 /* Grab the data according to data type */
5444 switch (data_type) {
5446 /* nothing to decode */
5449 /* nothing to decode */
5452 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5454 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5455 *offset-sizeof(s_octet2),2,s_octet2);
5459 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5461 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5462 *offset-sizeof(s_octet4),4,s_octet4);
5466 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5468 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5469 *offset-sizeof(u_octet2),2,u_octet2);
5473 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5475 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5476 *offset-sizeof(u_octet4),4,u_octet4);
5480 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5482 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5483 *offset-sizeof(my_float),4,my_float);
5487 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5489 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5490 *offset-sizeof(my_double),8,my_double);
5494 my_boolean = get_CDR_boolean(tvb,offset);
5496 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5497 *offset-1,1,my_boolean);
5501 u_octet1 = get_CDR_char(tvb,offset);
5503 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5504 *offset-sizeof(u_octet1),1,u_octet1);
5508 u_octet1 = get_CDR_octet(tvb,offset);
5510 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5511 *offset-sizeof(u_octet1),1,u_octet1);
5515 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5518 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5529 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5531 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5532 *offset-sizeof(u_octet4),4,u_octet4);
5536 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5538 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5539 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5541 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5542 *offset-u_octet4,u_octet4,buf);
5546 g_free(buf); /* dont forget */
5563 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5566 * XXX - can any of these throw an exception?
5567 * If so, we need to catch the exception and free "buf".
5569 if (s_octet1 < 0) { /* no size to add to tree */
5570 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5571 *offset+s_octet1,(-s_octet1),buf);
5573 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5574 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5575 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5576 *offset-s_octet1,s_octet1,buf);
5580 g_free(buf); /* dont forget */
5583 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5586 * XXX - can any of these throw an exception?
5587 * If so, we need to catch the exception and free "buf".
5589 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5590 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5591 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5592 *offset-u_octet4,u_octet4,buf);
5595 g_free(buf); /* dont forget */
5605 case tk_abstract_interface:
5608 g_warning("giop: Unknown typecode data type %u \n", data_type);