2 * Routines for CORBA GIOP/IIOP packet disassembly
5 * Laurent Deniel <laurent.deniel@free.fr>
6 * Craig Rodrigues <rodrigc@attbi.com>
8 * GIOP API extensions by,
9 * Frank Singleton <frank.singleton@ericsson.com>
10 * Trevor Shepherd <eustrsd@am1.ericsson.se>
14 * Ethereal - Network traffic analyzer
15 * By Gerald Combs <gerald@ethereal.com>
16 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 * 1. heuristic giop dissector table [started]
37 * 2. GUI options, see 20
38 * 3. Remove unneccessary reply_status in heuristic dissector calls (now
39 * part of MessageHeader) [done]
40 * 4. get_CDR_xxx should be passed an alignment offset value
41 * rather than GIOP_HEADER_SIZE, as alignment can also change in a
42 * octet stream when eg: encapsulation is used [done]
43 * 5. GIOP users should eventually get there own tvbuff, and
44 * not rely on the GIOP tvbuff, more robust
45 * 6. get_CDR_string,wchar,wstring etc should handle different
46 * GIOP versions [started]
47 * 7. Fix situation where req_id is not unique in a logfile [done, use FN/MFN, needs improving.]
49 * 8. Keep request_1_2 in step with request_1_1 [started]
50 * 9. Explicit module name dissection [done]
51 * 10. Decode IOR and put in a useful struct [IOR decode started]
52 * 11. Fix encapsulation of IOR etc and boundary [done]
53 * 12. handle get_CDR_typeCode() [started]
54 * 13. Handle different IOR profiles
55 * 14. Change printable_string to RETURN a new string, not to modify the old.
56 * or, new function, make_printable_string [done, make_printable_string]
58 * 15. Handle "TCKind", and forget about eg: enum translation to symbolic values
59 * otherwise need knowledge of sub dissectors data - YUK [done]
60 * 16. Handle multiple RepoId representations, besides IDL:Echo:1.0 (see 13.)
61 * 17. Pass subset of RepoID to explicit dissector.
62 * eg : If IDL:Mod1/Mod2/Int3:1.0 then pass "Mod1/Mode2/Int3" to sub dissector[done]
63 * 18. Better hashing algorithms
64 * 19. Handle hash collision properly .
65 * 20. Allow users to paste a stringified IOR into the GUI, and tie it
67 * 21. Add complete_request_packet_list and complete_reply_packet_hash.[done]
68 * 22. Handle case where users click in any order, AND try and match
69 * REPLY msg to the correct REQUEST msg when we have a request_id collision.[done]
70 * 23. Clean up memory management for all those g_malloc's etc
71 * 24. register_giop_user_module could return a key for every distinct Module/Interface
72 * the sub_dissector uses. So, instead of strcmp()'s when handling the
73 * namespace of an operation, we could have a lookup table instead.
74 * 25. A few typedefs in the right place.
75 * 26 Improve handling of gchar * and use const gchar * where possible.
76 * 27. Read/write IOR etc to/from file, allows objkey hash to be built from
77 * external data [read done, write incomplete]
78 * 28. Call sub dissector only if tvb_offset_exists(). [Done, this is checked
79 * inside try_explicit_giop_dissector() ]
81 * 29. Make add/delete routine for objkey hash as it may be useful when say reading
82 * stringified IOR's from a file to add them to our hash. ie: There are other ways
83 * to populate our object key hash besides REPLY's to RESOLVE(request) [done]
85 * 30. Add routine to encode/decode stringified IOR's [decode done]
86 * 31. Add routine to read IOR's from file [done]
87 * 32. TypeCode -none-, needs decoding.
88 * 33. Complete dissect_data_for_typecode.
89 * 34. For complex TypeCodes need to check final offset against original offset + sequence length.
90 * 35. Update REQUEST/REPLY 1_2 according to IDL (eg; ServiceContextList etc).
91 * 36. Adding decode_ServiceContextList, incomplete.
92 * 37. Helper functions should not ALWAYS rely on header to find current endianess. It should
93 * be passed from user, eg Use stream_is_big_endian. [started]
94 * 38. Remove unwanted/unused function parameters, see decode_IOR [started]
95 * 40. Add sequence <IOP::TaggedComponent> components to IIOP IOR profile. Perhaps
96 * decode_IOP_TaggedComponents as a helper function. [done - NOT helper]
98 * 41. Make important field searchable from Message header. ie: Remove add_text_
99 * 42. Use sub-tree for decode_ServiceContextList, looks better.
100 * 43. dissect_reply_body, no exception dissector calls
101 * - call subdiss directly, as we already have handle.
102 * - add repoid to heuristic call also.
104 * 44. typedef using xxx_t in .h file.
105 * 45. Subdissectors should not be passed MessageHeader to find endianness and
106 * version, they should be passed directly ?
107 * 46. get_CDR_wchar and wstring need wide chars decoded (just dumped in
108 * any readable form at present, not handled well at all, suggestions welcome -- FS
109 * 47. Change ...add_text to ...add_xxx (ie use hf fields).
111 * 48. BUG - file load with a GIOP filter set, causes the FN/MFN data struct to be
112 * not initiated properly. Hit "Reload" as a workaround, til I fix this -- FS
119 * Intended Decode strategy:
120 * =========================
124 * REQUEST: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
125 * and populate complete_request_packet_hash
127 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
132 * REQUEST: FN -> giop_sub_handle_t directly (via complete_request_packet_hash)
134 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
135 * (via complete_request_packet_hash
141 * 1. Request_ID's are unique only per connection.
143 * 2. You must be monitoring the network when the client does
144 * a REQUEST(resolve), otherwise I have no knowledge of the
145 * association between object_key and REPOID. I could talk to
146 * a Nameserver, but then I would start "generating" packets.
147 * This is probably not a good thing for a protocol analyser.
148 * Also, how could I decode logfiles offline.
150 * TODO -- Read stringified IORs from an input file.[done]
152 * 3. User clicks (REQUEST) is currently handle the same as
153 * the initial pass handling.
155 * ie: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
160 * Important Data Structures:
165 * This is a hash table that maps IDL Module/Interface Names (Key)
166 * to sub_dissector handles, giop_sub_handle_t. It is populated
167 * by subdissectors, via register_giop_user_module(). This
168 * table is used when we have a REPOID, and explicitly wish to
169 * call the subdissector that has registered responsibility for
170 * that IDL module/interface.
176 * This singly linked list is used to hold entries for
177 * heuristic based subdissectors. It is populated by sub_dissectors
178 * wishing to be called via heuristic mechanisms. They do this
179 * via the register_giop_user() function.
185 * This hash table maps object_key's (key) onto REPOID's (val).
186 * Once a client has REQUEST(resolve) an object , it knows about
187 * an object (interface) via its object_key (see IOR). So in order to follow
188 * packets that contain an object_key only, and to be able to forward it
189 * to the correct explicit subdissector, we need this table.
191 * So, I listen in on REQUEST(resolve) messages between client and
192 * Nameserver, and store the respones (REPLY/Objkey,Repo_ID) here.
194 * Also, stringified IOR's can be read from a file "IOR.txt" and used
195 * to populate this hash also.
198 * Other Data structures
199 * =======================
201 * These structures have been added to minimise the possibility
202 * of incorrectly interpreted packets when people click all
203 * over the place, in no particular order, when the request_id's are
204 * not unique as captured. If all request_is'd are unique, as captured, then
205 * we would not have to deal with this problem.
208 * When the logfile or packets are initially being processed, I will
209 * build 2 structures. The intent is to be able to map a REPLY message
210 * back to the most recent REQUEST message with the same Request_ID
211 * (TODO and matching port and IP address ??)
217 * MFN - Matching Frame Number
220 * complete_request_packet_list
221 * ----------------------------
223 * This is a list that contains ALL the FN's that are REQUEST's, along with
224 * operation,request_id and giop_sub_handle_t
226 * complete_reply_packet_hash
227 * --------------------------
229 * This is a hash table. It is populated with FN (key) and MFN (val).
230 * This allows me to handle the case, where if you click on any REPLY
231 * message, I can lookup the matching request. This can improve
232 * the match rate between REQUEST and REPLY when people click in
233 * any old fashion, but is NOT foolproof.
235 * The algorithm I use to populate this hash during initial pass,
238 * If packet is a REPLY, note the reqid, and then traverse backwards
239 * through the complete_request_packet_list from its tail, looking
240 * for a FN that has the same Request_id. Once found, take the found FN
241 * from complete_reply_packet_hash, and insert it into the MFN field
242 * of the complete_reply_packet_hash.
245 * See TODO for improvements to above algorithm.
247 * So now when people click on a REQUEST packet, I can call lookup the
248 * giop_sub_handle_t directly from complete_request_packet_list.
250 * And, when they click on a REPLY, I grab the MFN of this FN from
251 * complete_reply_packet_hash, then look that up in the complete_request_packet_list
252 * and call the sub_dissector directly.
254 * So, how do I differentiate between the initial processing of incoming
255 * packets, and a user clickin on one ? Good question.
257 * I leverage the pinfo_fd->flags.visited on a per frame
260 * To quote from the ever helpful development list
262 * " When a capture file is initially loaded, all "visited" flags
263 * are 0. Ethereal then makes the first pass through file,
264 * sequentially dissecting each packet. After the packet is
265 * dissected the first time, "visited" is 1. (See the end of
266 * dissect_packet() in epan/packet.c; that's the code that
267 * sets "visited" to 1).
269 * By the time a user clicks on a packet, "visited" will already
270 * be 1 because Ethereal will have already done its first pass
271 * through the packets.
273 * Reload acts just like a normal Close/Open, except that it
274 * doesn't need to ask for a filename. So yes, the reload button
275 * clears the flags and re-dissects the file, just as if the file
276 * had been "opened". "
291 #ifdef NEED_STRERROR_H
292 #include "strerror.h"
297 #include <epan/packet.h>
298 #include <epan/conversation.h>
299 #include <epan/emem.h>
300 #include <epan/prefs.h>
302 #include "packet-giop.h"
303 #include "packet-tcp.h"
306 * Set to 1 for DEBUG output - TODO make this a runtime option
314 * ------------------------------------------------------------------------------------------+
315 * Private Helper function Declarations
316 * ------------------------------------------------------------------------------------------+
320 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
321 guint32 boundary, gboolean new_endianess, gchar *repobuf,
322 gboolean store_flag);
324 static void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *tree, int *offset,
325 gboolean stream_is_be, guint32 boundary);
327 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
328 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf);
330 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
331 guint32 boundary, gboolean stream_is_big_endian );
333 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
334 gboolean stream_is_big_endian,
337 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
338 gboolean stream_is_big_endian, guint32 boundary);
340 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
341 gboolean stream_is_big_endian, guint32 boundary,
342 MessageHeader * header);
344 static void dissect_tk_union_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_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
349 gboolean stream_is_big_endian, guint32 boundary);
351 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
352 gboolean stream_is_big_endian, guint32 boundary,
353 MessageHeader * header);
355 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
356 gboolean stream_is_big_endian, guint32 boundary,
357 MessageHeader * header);
359 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
360 gboolean stream_is_big_endian, guint32 boundary,
361 MessageHeader * header);
363 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
364 gboolean stream_is_big_endian, guint32 boundary,
365 MessageHeader * header);
367 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
368 gboolean stream_is_big_endian, guint32 boundary,
369 MessageHeader * header);
371 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
372 gboolean stream_is_big_endian, guint32 boundary,
373 MessageHeader * header);
375 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
376 gboolean stream_is_big_endian, guint32 boundary);
378 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
379 gboolean stream_is_big_endian, guint32 boundary);
382 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
383 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
385 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
386 gboolean stream_is_big_endian, guint32 boundary,
387 MessageHeader * header, guint32 data_type );
393 * ------------------------------------------------------------------------------------------+
394 * Data/Variables/Structs
395 * ------------------------------------------------------------------------------------------+
399 static int proto_giop = -1;
400 static int hf_giop_message_type = -1;
401 static int hf_giop_message_size = -1;
402 static int hf_giop_repoid = -1;
403 static int hf_giop_req_id = -1;
404 static int hf_giop_req_operation = -1;
405 static int hf_giop_string_length = -1;
406 static int hf_giop_sequence_length = -1;
407 static int hf_giop_profile_id = -1;
408 static int hf_giop_type_id = -1;
409 static int hf_giop_iiop_v_maj = -1;
410 static int hf_giop_iiop_v_min = -1;
411 static int hf_giop_endianess = -1; /* esp encapsulations */
412 static int hf_giop_IOR_tag = -1;
413 static int hf_giop_IIOP_tag = -1;
415 static int hf_giop_TCKind = -1;
416 static int hf_giop_typecode_count = -1;
417 static int hf_giop_typecode_default_used = -1;
418 static int hf_giop_typecode_digits = -1;
419 static int hf_giop_typecode_length = -1;
420 static int hf_giop_typecode_max_length = -1;
421 static int hf_giop_typecode_member_name = -1;
422 static int hf_giop_typecode_name = -1;
423 static int hf_giop_typecode_scale = -1;
424 static int hf_giop_typecode_ValueModifier = -1;
425 static int hf_giop_typecode_Visibility = -1;
427 static int hf_giop_type_boolean = -1;
428 static int hf_giop_type_char = -1;
429 static int hf_giop_type_double = -1;
430 static int hf_giop_type_enum = -1;
431 static int hf_giop_type_float = -1;
432 static int hf_giop_type_long = -1;
433 static int hf_giop_type_octet = -1;
434 static int hf_giop_type_short = -1;
435 static int hf_giop_type_string = -1;
436 static int hf_giop_type_ulong = -1;
437 static int hf_giop_type_ushort = -1;
439 static int hf_giop_iiop_host = -1;
440 static int hf_giop_iiop_port = -1;
441 static int hf_giop_iop_vscid = -1;
442 static int hf_giop_iop_scid = -1;
444 static int hf_giop_reply_status = -1;
445 static int hf_giop_exception_id = -1;
446 static int hf_giop_objekt_key = -1;
452 static gint ett_giop = -1;
453 static gint ett_giop_reply = -1;
454 static gint ett_giop_request = -1;
455 static gint ett_giop_cancel_request = -1;
456 static gint ett_giop_locate_request = -1;
457 static gint ett_giop_locate_reply = -1;
458 static gint ett_giop_fragment = -1;
460 static gint ett_giop_scl = -1; /* ServiceContextList */
461 static gint ett_giop_scl_st1 = -1;
462 static gint ett_giop_ior = -1; /* IOR */
464 static dissector_handle_t data_handle;
465 static dissector_handle_t giop_tcp_handle;
468 static const value_string giop_endianess_vals[] = {
469 { 0x0, "Big Endian" },
470 { 0x1, "Little Endian" },
474 static const value_string sync_scope[] = {
475 { 0x0, "SYNC_NONE" },
476 { 0x1, "SYNC_WITH_TRANSPORT"},
477 { 0x2, "SYNC_WITH_SERVER"},
478 { 0x3, "SYNC_WITH_TARGET"},
484 static const value_string profile_id_vals[] = {
485 { 0x0, "TAG_INTERNET_IOP" },
486 { 0x1, "TAG_MULTIPLE_COMPONENTS"},
487 { 0x2, "TAG_SCCP_IOP"},
491 static const value_string giop_message_types[] = {
494 { 0x2, "CancelRequest"},
495 { 0x3, "LocateRequest"},
496 { 0x4, "LocateReply"},
497 { 0x5, "CloseConnection"},
498 { 0x6, "MessageError"},
503 static const value_string giop_locate_status_types[] = {
504 { 0x0, "Unknown Object" },
505 { 0x1, "Object Here"},
506 { 0x2, "Object Forward"},
507 { 0x3, "Object Forward Perm"},
508 { 0x4, "Loc System Exception"},
509 { 0x5, "Loc Needs Addressing Mode"},
513 static const value_string tckind_vals[] = {
526 { 12, "tk_TypeCode"},
527 { 13, "tk_Principal"},
533 { 19, "tk_sequence"},
537 { 23, "tk_longlong"},
538 { 24, "tk_ulonglong"},
539 { 25, "tk_longdouble"},
544 { 30, "tk_value_box"},
546 { 32, "tk_abstract_interface"},
551 * These values are taken from the CORBA 3.0.2 standard,
552 * section 13.7.1 "Standard Service Contexts".
554 static const guint32 max_service_context_id = 0x10;
555 static const value_string service_context_ids[] = {
556 { 0x00, "TransactionService" },
558 { 0x02, "ChainBypassCheck"},
559 { 0x03, "ChainBypassInfo"},
560 { 0x04, "LogicalThreadId"},
561 { 0x05, "BI_DIR_IIOP"},
562 { 0x06, "SendingContextRunTime"},
563 { 0x07, "INVOCATION_POLICIES"},
564 { 0x08, "FORWARDED_IDENTITY"},
565 { 0x09, "UnknownExceptionInfo"},
566 { 0x0a, "RTCorbaPriority"},
567 { 0x0b, "RTCorbaPriorityRange"},
568 { 0x0c, "FT_GROUP_VERSION"},
569 { 0x0d, "FT_REQUEST"},
570 { 0x0e, "ExceptionDetailMessage"},
571 { 0x0f, "SecurityAttributeService"},
572 { 0x10, "ActivityService"},
579 #define GIOP_MAGIC "GIOP"
582 * TAGS for IOR Profiles
584 * Chapter 13 Corba 2.4.2
588 #define IOP_TAG_INTERNET_IOP 0
589 #define IOP_TAG_MULTIPLE_COMPONENTS 1
592 /* Max Supported versions */
594 static const guint GIOP_MAJOR = 1;
595 static const guint GIOP_MINOR = 2;
598 static const int KeyAddr = 0;
599 static const int ProfileAddr = 1;
600 static const int ReferenceAddr = 2;
604 static const value_string reply_status_types[] = {
605 { NO_EXCEPTION, "No Exception" } ,
606 { USER_EXCEPTION, "User Exception" } ,
607 { SYSTEM_EXCEPTION, "System Exception" } ,
608 { LOCATION_FORWARD, "Location Forward" } ,
609 { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
610 { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
616 typedef enum LocateStatusType
621 OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
622 LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
623 LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
627 typedef struct LocateReplyHeader
630 guint32 locate_status;
636 * DATA - complete_request_list
639 static GList *giop_complete_request_list;
641 struct comp_req_list_entry {
642 guint32 fn; /* frame number */
643 gchar * operation; /* echo echoString */
644 giop_sub_handle_t *subh; /* handle to sub dissector */
645 guint32 reqid; /* request id */
646 gchar * repoid; /* repository ID */
649 typedef struct comp_req_list_entry comp_req_list_entry_t;
653 * DATA - complete_reply_hash
655 * Maps reply FN to request MFN
658 struct complete_reply_hash_key {
659 guint32 fn; /* reply frame number */
662 struct complete_reply_hash_val {
663 guint32 mfn; /* matching frame number (request) */
666 GHashTable *giop_complete_reply_hash = NULL; /* hash */
669 * DATA - Module Hash stuff to store data from register_giop_user_module
671 * ie: module (or interface ?) name, and ptr to sub_dissector handle
673 * With this knowledge, we can call a sub dissector directly,
676 * objkey -> repoid -> sub_dissector via registered module/interface
681 static int giop_module_init_count = 100; /* storage size for our permanent data */
682 /* ie: 100 entries -- needs tweaking -- FS */
684 struct giop_module_key {
685 gchar *module; /* module (interface?) name */
688 struct giop_module_val {
689 giop_sub_handle_t *subh; /* handle to sub dissector */
692 GHashTable *giop_module_hash = NULL; /* hash */
696 * DATA - GSList to store list of function (dissector) pointers.
697 * for heuristic dissection.
701 static GSList *giop_sub_list = NULL;
704 * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
705 * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
707 * With this knowledge, we can call a sub dissector directly later
710 * objkey -> repoid -> sub_dissector via registered module/interface
712 * rather than heuristic calls that do not provide operation context.
713 * (unless we pass the RepoID for a given objkey -- hmmm)
718 * Interesting operation list, add more if you want to save
722 static const char giop_op_resolve[] = "resolve";
723 static const char giop_op_bind_new_context[] = "bind_new_context";
724 static const char giop_op_bind[] = "bind";
725 static const char giop_op_is_a[] = "_is_a";
728 * Enums for interesting local operations, that we may need to monitor
729 * with their subsequent replies
734 request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
735 request_bind_new_context_op_val, /* bind_new_context */
736 request_bind_op_val, /* bind */
737 request_get_INIT_op_val /* finding Nameserver */
743 * hash for mapping object keys onto object namespaces, so
744 * I can call the correct dissector.
750 * Where did I get the IOR from.
754 req_res = 0, /* REQUEST (resolve) */
755 file /* stringified IOR' in a file */
759 typedef enum ior_src ior_src_t;
764 * Enums for my lists and hash's
767 enum collection_data {
768 cd_heuristic_users = 0,
771 cd_complete_request_list,
772 cd_complete_reply_hash
775 typedef enum collection_data collection_data_t;
779 struct giop_object_key {
780 guint8 *objkey; /* ptr to object key */
781 guint32 objkey_len; /* length */
784 struct giop_object_val {
785 guint8 *repo_id; /* ptr to Repository ID string */
786 ior_src_t src; /* where did Iget this IOR from */
789 GHashTable *giop_objkey_hash = NULL; /* hash */
792 gboolean giop_desegment = TRUE;
795 * ------------------------------------------------------------------------------------------+
796 * Private helper functions
797 * ------------------------------------------------------------------------------------------+
803 * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
806 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
807 GList * newlist_start;
808 comp_req_list_entry_t * entry = NULL;
811 entry = g_malloc(sizeof(comp_req_list_entry_t));
812 opn = g_strdup(op); /* duplicate operation for storage */
815 entry->reqid = reqid;
817 entry->operation = opn;
818 entry->repoid = NULL; /* dont have yet */
820 newlist_start = g_list_append (list, entry); /* append */
822 return newlist_start;
827 * Used to find an entry with matching Frame Number FN
828 * in the complete_request_list list.
831 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
833 GList * element; /* entry in list */
834 comp_req_list_entry_t * entry_ptr = NULL;
836 element = g_list_last(giop_complete_request_list); /* start from last */
838 while(element) { /* valid list entry */
839 entry_ptr = element->data; /* grab data pointer */
840 if (entry_ptr->fn == fn) { /* similar FN */
843 element = g_list_previous(element); /* try next previous */
846 return NULL; /* no match so return NULL */
851 * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
853 * Call this when you know a FN and matching giop_sub_handle_t and repoid
855 * This is done in say, try_explicit_dissector for example.
859 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
861 comp_req_list_entry_t * entry = NULL;
862 entry = find_fn_in_list(fn); /* grab FN data entry */
866 entry->repoid = g_strdup(repoid); /* copy and store */
874 /* giop_complete_reply_hash "EQUAL" Functions */
876 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
877 const struct complete_reply_hash_key *mk1 = (const struct complete_reply_hash_key *)v;
878 const struct complete_reply_hash_key *mk2 = (const struct complete_reply_hash_key *)w;
880 if (mk1->fn == mk2->fn) {
884 return 0; /* found differences */
887 /* giop_complete_reply_hash "HASH" Functions */
889 static guint32 complete_reply_hash_fn(gconstpointer v) {
890 guint32 val; /* init hash value */
891 const struct complete_reply_hash_key *key = (const struct complete_reply_hash_key *)v;
893 val = key->fn; /* simple and unique */
900 * Insert the FN and MFN together in our complete_reply_hash.
903 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
905 struct complete_reply_hash_key key, *new_key;
906 struct complete_reply_hash_val *val = NULL;
910 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
913 return; /* FN collision */
916 new_key = se_alloc(sizeof(struct complete_reply_hash_key));
917 new_key->fn = fn; /* save FN */
919 val = se_alloc(sizeof(struct complete_reply_hash_val));
920 val->mfn = mfn; /* and MFN */
922 g_hash_table_insert(giop_complete_reply_hash, new_key, val);
927 * Find the MFN values from a given FN key.
928 * Assumes the complete_reply_hash is already populated.
931 static guint32 get_mfn_from_fn(guint32 fn) {
933 struct complete_reply_hash_key key;
934 struct complete_reply_hash_val *val = NULL;
935 guint32 mfn = fn; /* save */
938 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
941 mfn = val->mfn; /* grab it */
944 return mfn; /* mfn or fn if not found */
949 * Attempt to find the MFN for this FN, and return it.
950 * Return MFN if found, or just FN if not. This is
951 * only used when we are building
954 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
956 GList * element; /* last entry in list */
957 comp_req_list_entry_t * entry_ptr = NULL;
959 /* Need Some pretty snappy code */
961 /* Loop back from current end of complete_request_list looking for */
962 /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
965 * As this routine is only called during initial pass of data,
966 * and NOT when a user clicks, it is ok to start from Current
967 * end of complete_request_list when searching for a match.
968 * As that list is bing populated in the same order as FN's
971 * Also, can make check for same reqid more detailed, but I start
972 * with reqid. Could add say port or address checks etc later ??
976 element = g_list_last(giop_complete_request_list); /* get last */
978 while(element) { /* valid list entry */
979 entry_ptr = element->data; /* grab data pointer */
980 if (entry_ptr->reqid == reqid) { /* similar reqid */
981 return entry_ptr->fn; /* return MFN */
983 element = g_list_previous(element); /* try next previous */
986 return fn; /* no match so return FN */
990 /* Module Hash "EQUAL" Functions */
992 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
993 const struct giop_module_key *mk1 = (const struct giop_module_key *)v;
994 const struct giop_module_key *mk2 = (const struct giop_module_key *)w;
996 if (strcmp(mk1->module, mk2->module) == 0) {
1000 return 0; /* found differences */
1003 /* Module Hash "HASH" Functions */
1005 static guint32 giop_hash_module_hash(gconstpointer v) {
1008 guint32 val = 0; /* init hash value */
1010 const struct giop_module_key *key = (const struct giop_module_key *)v;
1013 * Hmm, try this simple hashing scheme for now.
1014 * ie: Simple summation, FIX later -- FS
1019 len = strlen(key->module);
1021 for (i=0; i<len; i++) {
1022 val += (guint8) key->module[i];
1031 * ------------------------------------------------------------------------------------------+
1032 * Public Utility functions
1033 * ------------------------------------------------------------------------------------------+
1040 * Routine to allow giop users to register their sub dissector function, name, and
1041 * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1042 * value returned from their proto_register_protocol(), so we can enable/disbale it
1043 * through the GUI (edit protocols).
1045 * This is used by try_explicit_giop_dissector() to find the
1046 * correct sub-dissector.
1050 void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
1052 struct giop_module_key module_key, *new_module_key;
1053 struct giop_module_val *module_val = NULL;
1055 module_key.module = module; /* module name */
1057 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1060 return; /* module name collision */
1063 /* So, passed module name should NOT exist in hash at this point.*/
1066 printf("giop:register_module: Adding Module %s to module hash \n", module);
1067 printf("giop:register_module: Module sub dissector name is %s \n", name);
1070 new_module_key = g_malloc(sizeof(struct giop_module_key));
1071 new_module_key->module = module; /* save Module or interface name from IDL */
1073 module_val = g_malloc(sizeof(struct giop_module_val));
1075 module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
1077 module_val->subh->sub_name = name; /* save dissector name */
1078 module_val->subh->sub_fn = sub; /* save subdissector*/
1079 module_val->subh->sub_proto = find_protocol_by_id(sub_proto); /* save protocol_t for subdissector's protocol */
1081 g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1088 /* Object Key Hash "EQUAL" Functions */
1090 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1091 const struct giop_object_key *v1 = (const struct giop_object_key *)v;
1092 const struct giop_object_key *v2 = (const struct giop_object_key *)w;
1094 if (v1->objkey_len != v2->objkey_len)
1095 return 0; /* no match because different length */
1097 /* Now do a byte comaprison */
1099 if (memcmp(v1->objkey,v2->objkey, v1->objkey_len) == 0) {
1100 return 1; /* compares ok */
1104 printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1107 return 0; /* found differences */
1110 /* Object Key Hash "HASH" Functions */
1112 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1113 const struct giop_object_key *key = (const struct giop_object_key *)v;
1116 guint32 val = 0; /* init hash value */
1120 * Hmm, try this simple hashing scheme for now.
1121 * ie: Simple summation
1127 printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1130 for (i=0; i< key->objkey_len; i++) {
1131 val += (guint8) key->objkey[i];
1139 * Routine to take an object key octet sequence, and length, and ptr to
1140 * a (null terminated )repository ID string, and store them in the obect key hash.
1142 * Blindly Inserts even if it does exist, See TODO at top for reason.
1145 static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
1147 struct giop_object_key objkey_key, *new_objkey_key;
1148 struct giop_object_val *objkey_val = NULL;
1150 objkey_key.objkey_len = len; /* length */
1151 objkey_key.objkey = obj; /* object key octet sequence */
1153 /* Look it up to see if it exists */
1155 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1157 /* CHANGED -- Same reqid, so abandon old entry */
1160 g_hash_table_remove(hash, &objkey_key);
1163 /* So, passed key should NOT exist in hash at this point.*/
1165 new_objkey_key = se_alloc(sizeof(struct giop_object_key));
1166 new_objkey_key->objkey_len = len; /* save it */
1167 new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */
1169 objkey_val = se_alloc(sizeof(struct giop_object_val));
1170 objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
1171 objkey_val->src = src; /* where IOR came from */
1175 printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
1176 objkey_val->repo_id, new_objkey_key->objkey_len);
1179 g_hash_table_insert(hash, new_objkey_key, objkey_val);
1186 * convert an ascii char representing a hex value,
1187 * to a numeric value.
1189 * returns value, or -1 if problem.
1193 static gint8 hex_char_to_val(guchar c){
1200 retval = c - 48; /* convert digit */
1204 c = toupper(c); /* convert to uppercase */
1205 if (c >= 'A' && c <= 'F') {
1216 * Convert from stringified IOR of the kind IOR:af4f7e459f....
1217 * to an IOR octet sequence.
1219 * User must free buffer.
1221 * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1222 * grab repoid etc for our objkey hash.
1226 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1229 gint8 tmpval; /* complete value */
1232 *out = g_new0(guint8, in_len); /* allocate buffer */
1238 /* skip past IOR: and convert character pairs to guint8 */
1240 for (i=4; i<in_len-1; i+=2) {
1241 if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1243 if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1244 g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1248 if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1249 g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1252 tmpval = tmpval_msb << 4;
1253 tmpval += tmpval_lsb;
1254 (*out)[(i-4)/2] = (guint8) tmpval;
1264 return (i-4)/2; /* length */
1271 * Simple "get a line" routine, copied from somewhere :)
1275 static int giop_getline(FILE *fp, gchar *line, int maxlen) {
1277 if (fgets(line,maxlen,fp) == NULL)
1280 return strlen(line);
1286 * Read a list of stringified IOR's from a named file, convert to IOR's
1287 * and store in object key hash
1290 static void read_IOR_strings_from_file(const gchar *name, int max_iorlen) {
1291 guchar *buf; /* NOTE reused for every line */
1293 int ior_val_len; /* length after unstringifying. */
1295 guint8 *out; /* ptr to unstringified IOR */
1296 tvbuff_t *tvb; /* temp tvbuff for dissectin IORs */
1297 guint32 my_offset = 0;
1298 gboolean stream_is_big_endian;
1301 fp = fopen(name,"r"); /* open read only */
1304 if (errno == EACCES)
1305 fprintf(stderr, "Error opening file %s for reading: %s\n", name, strerror(errno));
1309 buf = g_malloc0(max_iorlen+1); /* input buf */
1311 while ((len = giop_getline(fp,buf,max_iorlen+1)) > 0) {
1312 my_offset = 0; /* reset for every IOR read */
1314 ior_val_len = string_to_IOR(buf,len,&out); /* convert */
1318 /* Combination of tvb_new() and tvb_set_real_data().
1319 Can throw ReportedBoundsError.
1321 XXX - can it throw an exception in this case? If so, we
1322 need to catch it and clean up, but we really shouldn't allow
1323 it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
1326 tvb = tvb_new_real_data(out, ior_val_len, ior_val_len);
1328 stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1329 decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1339 fclose(fp); /* be nice */
1347 * Init routine, setup our request hash stuff, or delete old ref's
1349 * Cannot setup the module hash here as my init() may not be called before
1350 * users start registering. So I will move the module_hash stuff to
1351 * proto_register_giop, as is done with packet-rpc
1355 * Also, setup our objectkey/repoid hash here.
1359 static void giop_init(void) {
1363 * Create objkey/repoid hash, use my "equal" and "hash" functions.
1367 if (giop_objkey_hash)
1368 g_hash_table_destroy(giop_objkey_hash);
1371 * Create hash, use my "equal" and "hash" functions.
1375 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1378 * Create complete_reply_hash, use my "equal" and "hash" functions.
1382 if (giop_complete_reply_hash)
1383 g_hash_table_destroy(giop_complete_reply_hash);
1387 * Create hash, use my "equal" and "hash" functions.
1391 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1394 read_IOR_strings_from_file("IOR.txt", 600); /* testing */
1401 * Insert an entry in the GIOP Heuristic User table.
1403 * Uses giop_sub_handle_t to wrap giop user info.
1407 void register_giop_user(giop_sub_dissector_t *sub, const gchar *name, int sub_proto) {
1409 giop_sub_handle_t *subh;
1411 subh = g_malloc(sizeof (giop_sub_handle_t));
1413 subh->sub_name = name;
1415 subh->sub_proto = find_protocol_by_id(sub_proto); /* protocol_t for sub dissectors's proto_register_protocol() */
1417 giop_sub_list = g_slist_append (giop_sub_list, subh);
1423 * Lookup an object key in our object key hash, and return the corresponding
1428 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1430 struct giop_object_key objkey_key;
1431 struct giop_object_val *objkey_val = NULL;
1433 objkey_key.objkey_len = len; /* length */
1434 objkey_key.objkey = obj; /* object key octet sequence */
1436 /* Look it up to see if it exists */
1438 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1442 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1444 return objkey_val->repo_id; /* found */
1448 printf("FAILED Lookup of object key \n" );
1451 return NULL; /* not found */
1457 * Extract top level module/interface from repoid
1459 * eg from - "IDL:Echo/interface1:1.0"
1462 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1463 * get linux.org/Penguin/Teeth
1466 * User must free returned ptr after use.
1468 * TODO -- generalize for other Repoid encodings
1471 static gchar * get_modname_from_repoid(gchar *repoid) {
1473 gchar *modname = NULL;
1474 gchar *saved_repoid = NULL;
1476 guint8 stop_mod = 0; /* Index of last character of modname in Repoid */
1477 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1480 saved_repoid = g_strdup(repoid); /* make a copy */
1482 /* Must start with IDL: , otherwise I get confused */
1484 if (g_strncasecmp("IDL:",repoid,4))
1487 /* Looks like a RepoID to me, so get Module or interface name */
1489 /* TODO -- put some code here to get Module name */
1491 for(i=4; c != '\0'; i++) {
1493 stop_mod = i; /* save */
1494 if (c == ':' ) /* delimiters */
1499 /* Now create a new string based on start and stop and \0 */
1501 modname = g_strndup(repoid+4, stop_mod - start_mod);
1516 * Display a "module" hash entry
1519 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1521 struct giop_module_val *mv = (struct giop_module_val *) val;
1522 struct giop_module_key *mk = (struct giop_module_key *) key;
1524 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1531 * Display a "complete_reply " hash entry
1534 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1536 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1537 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1539 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1547 * Display an "objkey" hash entry
1550 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1552 struct giop_object_val *mv = (struct giop_object_val *) val;
1553 struct giop_object_key *mk = (struct giop_object_key *) key;
1556 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1558 for (i=0; i<mk->objkey_len; i++) {
1559 printf("%.2x ", mk->objkey[i]);
1563 * If read from file, mark it as such..
1567 printf(", Repo ID = %s \n", mv->repo_id);
1570 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1578 * Display all giop_sub_list (GSList) entries
1581 static void display_heuristic_user_list() {
1584 giop_sub_handle_t *subh; /* handle */
1586 /* Get length of list */
1587 len = g_slist_length(giop_sub_list); /* find length */
1592 for (i=0; i<len; i++) {
1593 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1594 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1600 * Display all complete_request_list (GList) entries
1603 static void display_complete_request_list() {
1606 comp_req_list_entry_t *entry;
1608 /* Get length of list */
1609 len = g_list_length(giop_complete_request_list); /* find length */
1614 for (i=0; i<len; i++) {
1615 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1616 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1617 entry->reqid,entry->operation, entry->repoid);
1625 /* Dump Hash/List contents
1627 * collection_type specifies the list or hash to dump
1631 static void giop_dump_collection(collection_data_t collection_type) {
1633 switch(collection_type) {
1634 case cd_heuristic_users:
1635 printf("+----------------------------------------------+ \n");
1636 printf("+-------------- Heuristic User (Begin) --------+ \n");
1637 printf("+----------------------------------------------+ \n");
1639 display_heuristic_user_list();
1641 printf("+----------------------------------------------+ \n");
1642 printf("+-------------- Heuristic User (End) ----------+ \n");
1643 printf("+----------------------------------------------+ \n");
1647 case cd_complete_request_list:
1648 printf("+----------------------------------------------+ \n");
1649 printf("+------------- Complete Request List (Begin) --+ \n");
1650 printf("+----------------------------------------------+ \n");
1652 display_complete_request_list();
1654 printf("+----------------------------------------------+ \n");
1655 printf("+------------ Complete Request List (End) -----+ \n");
1656 printf("+----------------------------------------------+ \n");
1660 case cd_module_hash:
1661 printf("+----------------------------------------------+ \n");
1662 printf("+-------------- Module (Begin) ----------------+ \n");
1663 printf("+----------------------------------------------+ \n");
1665 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1667 printf("+----------------------------------------------+ \n");
1668 printf("+-------------- Module ( End) -----------------+ \n");
1669 printf("+----------------------------------------------+ \n\n");
1673 case cd_objkey_hash:
1674 printf("+----------------------------------------------+ \n");
1675 printf("+-------------- Objkey (Begin) ----------------+ \n");
1676 printf("+----------------------------------------------+ \n");
1678 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1680 printf("+----------------------------------------------+ \n");
1681 printf("+-------------- Objkey (End) ------------------+ \n");
1682 printf("+----------------------------------------------+ \n\n");
1686 case cd_complete_reply_hash:
1687 printf("+----------------------------------------------+ \n");
1688 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1689 printf("+----------------------------------------------+ \n");
1691 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1693 printf("+----------------------------------------------+ \n");
1694 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1695 printf("+----------------------------------------------+ \n");
1701 printf("giop: giop_dump_collection: Unknown type \n");
1712 * Loop through all subdissectors, and call them until someone
1713 * answers (returns TRUE). This function then returns TRUE, otherwise
1716 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1719 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1720 MessageHeader *header, gchar *operation ) {
1723 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1724 giop_sub_handle_t *subh = NULL;
1725 const char *saved_proto;
1727 len = g_slist_length(giop_sub_list); /* find length */
1732 saved_proto = pinfo->current_proto;
1733 for (i=0; i<len; i++) {
1734 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1736 if (proto_is_protocol_enabled(subh->sub_proto)) {
1737 pinfo->current_proto =
1738 proto_get_protocol_short_name(subh->sub_proto);
1739 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1741 pinfo->current_proto = saved_proto;
1742 return TRUE; /* found one, lets return */
1744 } /* protocol_is_enabled */
1747 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1748 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
1750 pinfo->current_proto = saved_proto;
1751 return res; /* result */
1757 * Find the matching repoid in the module hash and call
1758 * the dissector function if offset exists.
1761 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1762 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1768 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1769 MessageHeader *header, gchar *operation, gchar *repoid ) {
1771 giop_sub_handle_t *subdiss = NULL; /* handle */
1772 gboolean res = FALSE;
1773 gchar *modname = NULL;
1774 struct giop_module_key module_key;
1775 struct giop_module_val *module_val = NULL;
1776 const char *saved_proto;
1780 * Get top level module/interface from complete repoid
1783 modname = get_modname_from_repoid(repoid);
1784 if (modname == NULL) {
1785 return res; /* unknown module name */
1789 /* Search for Module or interface name */
1791 module_key.module = modname; /* module name */
1792 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1794 if (module_val == NULL) {
1795 return res; /* module not registered */
1798 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1801 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1802 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1803 /* but only if user not clicking */
1805 if (!pinfo->fd->flags.visited)
1806 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1809 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1811 if (tvb_offset_exists(tvb, *offset)) {
1813 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1816 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1818 saved_proto = pinfo->current_proto;
1819 pinfo->current_proto =
1820 proto_get_protocol_short_name(subdiss->sub_proto);
1821 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1822 pinfo->current_proto = saved_proto;
1824 } /* protocol_is_enabled */
1825 } /* offset exists */
1828 return res; /* return result */
1833 /* Take in an array of char and create a new string.
1834 * Replace non-printable characters with periods.
1836 * The array may contain \0's so dont use strdup
1837 * The string is \0 terminated, and thus longer than
1838 * the initial sequence.
1839 * Caller must free the new string.
1842 gchar * make_printable_string (gchar *in, guint32 len) {
1844 gchar *print_string = NULL;
1846 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1847 memcpy(print_string, in, len); /* and make a copy of input data */
1849 for(i=0; i < len; i++) {
1850 if( !isprint( (unsigned char)print_string[i] ) )
1851 print_string[i] = '.';
1854 return print_string; /* return ptr */
1857 /* Determine the byte order from the GIOP MessageHeader */
1859 gboolean is_big_endian (MessageHeader * header) {
1860 gboolean big_endian = FALSE;
1862 switch (header->GIOP_version.minor) {
1865 if (header->flags & 0x01)
1885 * Calculate new offset, based on the current offset, and user supplied
1886 * "offset delta" value, and the alignment requirement.
1890 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1891 * aligned on 8 byte boundaries.
1894 static void set_new_alignment(int *offset, int delta, int alignment) {
1896 while( ( (*offset + delta) % alignment) != 0)
1905 * ------------------------------------------------------------------------------------------+
1906 * Public get_CDR_xxx functions.
1907 * ------------------------------------------------------------------------------------------+
1913 * Gets data of type any. This is encoded as a TypeCode
1914 * followed by the encoded value.
1917 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1918 gboolean stream_is_big_endian, int boundary,
1919 MessageHeader * header ) {
1921 guint32 TCKind; /* TypeCode */
1923 /* get TypeCode of any */
1924 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1926 /* dissect data of type TCKind */
1927 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1931 /* Copy a 1 octet sequence from the tvbuff
1932 * which represents a boolean value, and convert
1933 * it to a boolean value.
1934 * Offset is then incremented by 1, to indicate the 1 octet which
1935 * has been processed.
1938 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1941 val = tvb_get_guint8(tvb, *offset); /* easy */
1946 /* Copy a 1 octet sequence from the tvbuff
1947 * which represents a char, and convert
1948 * it to an char value.
1949 * offset is then incremented by 1, to indicate the 1 octet which
1950 * has been processed.
1953 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1956 val = tvb_get_guint8(tvb, *offset); /* easy */
1964 * Floating Point Data Type double IEEE 754-1985
1966 * Copy an 8 octet sequence from the tvbuff
1967 * which represents a double value, and convert
1968 * it to a double value, taking into account byte order.
1969 * offset is first incremented so that it falls on a proper alignment
1970 * boundary for double values.
1971 * offset is then incremented by 8, to indicate the 8 octets which
1972 * have been processed.
1975 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1979 /* double values must be aligned on a 8 byte boundary */
1981 while( ( (*offset + boundary) % 8) != 0)
1984 val = (stream_is_big_endian) ? tvb_get_ntohieee_double (tvb, *offset) :
1985 tvb_get_letohieee_double (tvb, *offset);
1993 /* Copy a 4 octet sequence from the tvbuff
1994 * which represents an enum value, and convert
1995 * it to an enum value, taking into account byte order.
1996 * offset is first incremented so that it falls on a proper alignment
1997 * boundary for an enum (4)
1998 * offset is then incremented by 4, to indicate the 4 octets which
1999 * have been processed.
2001 * Enum values are encoded as unsigned long.
2005 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2007 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2013 * Copy an octet sequence from the tvbuff
2014 * which represents a Fixed point decimal type, and create a string representing
2015 * a Fixed point decimal type. There are no alignment restrictions.
2016 * Size and scale of fixed decimal type is determined by IDL.
2018 * digits - IDL specified number of "digits" for this fixed type
2019 * scale - IDL specified "scale" for this fixed type
2022 * eg: typedef fixed <5,2> fixed_t;
2023 * could represent numbers like 123.45, 789.12,
2026 * As the fixed type could be any size, I will not try to fit it into our
2027 * simple types like gdouble or glong etc. I will just create a string buffer holding
2028 * a representation (after scale is applied), and with a decimal point or zero padding
2029 * inserted at the right place if necessary. The string is null terminated
2031 * so string may look like
2034 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2036 * According to spec, digits <= 31
2037 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2040 * User must remember to free the buffer
2045 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2047 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2048 guint32 i ; /* loop */
2049 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2050 /* this does not include sign, decimal point and \0 */
2051 guint32 sindex = 0; /* string index */
2052 gchar *tmpbuf; /* temp buff, holds string without scaling */
2053 guint8 tval; /* temp val storage */
2056 * how many bytes to hold digits and scale (if scale <0)
2058 * eg: fixed <5,2> = 5 digits
2059 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2063 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2067 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2069 slen = digits; /* digits */
2073 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2076 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2079 * Register a cleanup function in case on of our tvbuff accesses
2080 * throws an exception. We need to clean up tmpbuf.
2082 CLEANUP_PUSH(g_free, tmpbuf);
2084 /* If even , grab 1st dig */
2086 if (!(digits & 0x01)) {
2087 tval = get_CDR_octet(tvb,offset);
2089 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2091 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2096 * Loop, but stop BEFORE we hit last digit and sign
2097 * if digits = 1 or 2, then this part is skipped
2101 for(i=0; i< ((digits-1)/2 ); i++) {
2102 tval = get_CDR_octet(tvb,offset);
2104 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2107 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2109 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2116 printf("giop:get_CDR_fixed(): before last digit \n");
2120 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2122 tval = get_CDR_octet(tvb,offset);
2124 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2126 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2129 sign = tval & 0x0f; /* get sign */
2131 /* So now, we have all digits in an array, and the sign byte
2132 * so lets generate a printable string, taking into account the scale
2136 sindex = 0; /* reset */
2137 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2138 * \0 -- TODO check slen is reasonable first */
2140 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2145 (*seq)[sindex] = '+'; /* put sign in first string position */
2148 (*seq)[sindex] = '-';
2151 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2152 (*seq)[sindex] = '*'; /* flag as sign unkown */
2158 /* Add decimal point or padding 0's, depending if scale is positive or
2159 * negative, respectively
2163 for (i=0; i<digits-scale; i++) {
2164 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2168 (*seq)[sindex] = '.'; /* decimal point */
2171 for (i=digits-scale; i<digits; i++) {
2172 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2176 (*seq)[sindex] = '\0'; /* string terminator */
2180 /* negative scale, dump digits and pad out with 0's */
2182 for (i=0; i<digits-scale; i++) {
2184 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2186 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2191 (*seq)[sindex] = '\0'; /* string terminator */
2196 * We're done with tmpbuf, so we can call the cleanup handler to free
2197 * it, and then pop the cleanup handler.
2199 CLEANUP_CALL_AND_POP;
2202 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2212 * Floating Point Data Type float IEEE 754-1985
2214 * Copy an 4 octet sequence from the tvbuff
2215 * which represents a float value, and convert
2216 * it to a float value, taking into account byte order.
2217 * offset is first incremented so that it falls on a proper alignment
2218 * boundary for float values.
2219 * offset is then incremented by 4, to indicate the 4 octets which
2220 * have been processed.
2223 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2227 /* float values must be aligned on a 4 byte boundary */
2229 while( ( (*offset + boundary) % 4) != 0)
2232 val = (stream_is_big_endian) ? tvb_get_ntohieee_float (tvb, *offset) :
2233 tvb_get_letohieee_float (tvb, *offset);
2242 * Decode an Interface type, and display it on the tree.
2245 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2246 gboolean stream_is_big_endian, int boundary) {
2249 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2255 /* Copy a 4 octet sequence from the tvbuff
2256 * which represents a signed long value, and convert
2257 * it to an signed long vaule, taking into account byte order.
2258 * offset is first incremented so that it falls on a proper alignment
2259 * boundary for long values.
2260 * offset is then incremented by 4, to indicate the 4 octets which
2261 * have been processed.
2264 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2268 /* unsigned long values must be aligned on a 4 byte boundary */
2269 while( ( (*offset + boundary) % 4) != 0)
2272 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2273 tvb_get_letohl (tvb, *offset);
2280 * Decode an Object type, and display it on the tree.
2283 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2284 gboolean stream_is_big_endian, int boundary) {
2286 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2292 /* Copy a 1 octet sequence from the tvbuff
2293 * which represents a octet, and convert
2294 * it to an octet value.
2295 * offset is then incremented by 1, to indicate the 1 octet which
2296 * has been processed.
2299 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2302 val = tvb_get_guint8(tvb, *offset); /* easy */
2308 /* Copy a sequence of octets from the tvbuff.
2309 * Caller of this function must remember to free the
2310 * array pointed to by seq.
2311 * This function also increments offset by len.
2314 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, guint32 len) {
2317 * Make sure that the entire sequence of octets is in the buffer before
2318 * allocating the buffer, so that we don't have to worry about freeing
2319 * the buffer, and so that we don't try to allocate a buffer bigger
2320 * than the data we'll actually be copying, and thus don't run the risk
2321 * of crashing if the buffer is *so* big that we fail to allocate it
2322 * and "g_new0()" aborts.
2324 tvb_ensure_bytes_exist(tvb, *offset, len);
2327 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2328 * do what we do now, and null-terminate the string (which also means
2329 * we don't need to zero out the entire allocation, just the last byte)?
2331 *seq = g_new0(gchar, len + 1);
2332 tvb_memcpy( tvb, *seq, *offset, len);
2337 /* Copy a 2 octet sequence from the tvbuff
2338 * which represents a signed short value, and convert
2339 * it to a signed short value, taking into account byte order.
2340 * offset is first incremented so that it falls on a proper alignment
2341 * boundary for short values.
2342 * offset is then incremented by 2, to indicate the 2 octets which
2343 * have been processed.
2346 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2350 /* short values must be aligned on a 2 byte boundary */
2351 while( ( (*offset + boundary) % 2) != 0)
2354 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2355 tvb_get_letohs (tvb, *offset);
2363 /* Copy an octet sequence from the tvbuff
2364 * which represents a string, and convert
2365 * it to an string value, taking into account byte order.
2366 * offset is first incremented so that it falls on a proper alignment
2367 * boundary for string values. (begins with an unsigned long LI)
2369 * String sequence is copied to a buffer "seq". This must
2370 * be freed by the calling program.
2371 * offset is then incremented, to indicate the octets which
2372 * have been processed.
2374 * returns number of octets in the sequence
2376 * Note: This function only supports single byte encoding at the
2377 * moment until I get a handle on multibyte encoding etc.
2382 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2387 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2390 (*offset)++; /* must step past \0 delimiter */
2394 get_CDR_octet_seq(tvb, seq, offset, slength);
2396 *seq = g_strdup(""); /* zero-length string */
2399 return slength; /* return length */
2403 /* Process a sequence of octets that represent the
2404 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2406 * This function also increments offset to the correct position.
2408 * It will parse the TypeCode and output data to the "tree" provided
2411 * It returns a guint32 representing a TCKind value.
2414 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2415 gboolean stream_is_big_endian, int boundary,
2416 MessageHeader * header ) {
2419 gint16 s_octet2; /* signed int16 */
2420 guint16 u_octet2; /* unsigned int16 */
2421 guint32 u_octet4; /* unsigned int32 */
2423 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2425 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2426 *offset-sizeof(val),4,val);
2429 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2432 case tk_null: /* empty parameter list */
2434 case tk_void: /* empty parameter list */
2436 case tk_short: /* empty parameter list */
2438 case tk_long: /* empty parameter list */
2440 case tk_ushort: /* empty parameter list */
2442 case tk_ulong: /* empty parameter list */
2444 case tk_float: /* empty parameter list */
2446 case tk_double: /* empty parameter list */
2448 case tk_boolean: /* empty parameter list */
2450 case tk_char: /* empty parameter list */
2452 case tk_octet: /* empty parameter list */
2454 case tk_any: /* empty parameter list */
2456 case tk_TypeCode: /* empty parameter list */
2458 case tk_Principal: /* empty parameter list */
2460 case tk_objref: /* complex parameter list */
2461 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary);
2463 case tk_struct: /* complex parameter list */
2464 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2466 case tk_union: /* complex parameter list */
2467 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2469 case tk_enum: /* complex parameter list */
2470 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary);
2473 case tk_string: /* simple parameter list */
2474 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2476 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2477 *offset-sizeof(u_octet4),4,u_octet4);
2481 case tk_sequence: /* complex parameter list */
2482 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2484 case tk_array: /* complex parameter list */
2485 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2487 case tk_alias: /* complex parameter list */
2488 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2490 case tk_except: /* complex parameter list */
2491 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2493 case tk_longlong: /* empty parameter list */
2495 case tk_ulonglong: /* empty parameter list */
2497 case tk_longdouble: /* empty parameter list */
2499 case tk_wchar: /* empty parameter list */
2501 case tk_wstring: /* simple parameter list */
2502 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2504 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2505 *offset-sizeof(u_octet4),4,u_octet4);
2509 case tk_fixed: /* simple parameter list */
2510 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2512 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2513 *offset-sizeof(u_octet2),2,u_octet2);
2516 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2518 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2519 *offset-sizeof(s_octet2),2,s_octet2);
2523 case tk_value: /* complex parameter list */
2524 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2526 case tk_value_box: /* complex parameter list */
2527 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2529 case tk_native: /* complex parameter list */
2530 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary);
2532 case tk_abstract_interface: /* complex parameter list */
2533 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary );
2536 g_warning("giop: Unknown TCKind %u \n", val);
2545 /* Copy a 4 octet sequence from the tvbuff
2546 * which represents an unsigned long value, and convert
2547 * it to an unsigned long vaule, taking into account byte order.
2548 * offset is first incremented so that it falls on a proper alignment
2549 * boundary for unsigned long values.
2550 * offset is then incremented by 4, to indicate the 4 octets which
2551 * have been processed.
2554 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2558 /* unsigned long values must be aligned on a 4 byte boundary */
2559 while( ( (*offset + boundary) % 4) != 0)
2562 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2563 tvb_get_letohl (tvb, *offset);
2570 /* Copy a 2 octet sequence from the tvbuff
2571 * which represents an unsigned short value, and convert
2572 * it to an unsigned short value, taking into account byte order.
2573 * offset is first incremented so that it falls on a proper alignment
2574 * boundary for unsigned short values.
2575 * offset is then incremented by 2, to indicate the 2 octets which
2576 * have been processed.
2579 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2583 /* unsigned short values must be aligned on a 2 byte boundary */
2584 while( ( (*offset + boundary) % 2) != 0)
2587 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2588 tvb_get_letohs (tvb, *offset);
2596 /* Copy a wchar from the tvbuff.
2597 * Caller of this function must remember to free the
2598 * array pointed to by seq.
2599 * This function also increments offset according to
2602 * For GIOP 1.1 read 2 octets and return size -2. The
2603 * negation means there is no size element in the packet
2604 * and therefore no size to add to the tree.
2606 * For GIOP 1.2 read size of wchar and the size
2607 * octets. size is returned as a gint8.
2609 * For both GIOP versions the wchar is returned
2610 * as a printable string.
2614 /* NOTE: This is very primitive in that it just reads
2615 * the wchar as a series of octets and returns them
2616 * to the user. No translation is attempted based on
2617 * byte orientation, nor on code set. I.e it only
2618 * really reads past the wchar and sets the offset
2622 /* The "decoding" is done according to CORBA chapter 15.
2623 * Wchar is not supported for GIOP 1.0.
2626 gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2631 /* CORBA chapter 15:
2632 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2633 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2634 * followed by the elements of the octet sequence representing
2635 * the encoded value of the wchar.
2638 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2639 slength = 2; /* set for GIOP 1.1 length in octets */
2641 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2642 slength = get_CDR_octet(tvb,offset);
2645 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2646 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2648 /* now turn octets (wchar) into something that can be printed by the user */
2649 *seq = make_printable_string(raw_wstring, slength);
2651 g_free(raw_wstring);
2654 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2655 if (header->GIOP_version.minor < 2)
2658 return slength; /* return length */
2663 /* Copy a wstring from the tvbuff.
2664 * Caller of this function must remember to free the
2665 * array pointed to by seq.
2666 * This function also increments offset, according to
2667 * wstring length. length is returned as guint32
2670 /* NOTE: This is very primitive in that it just reads
2671 * the wstring as a series of octets and returns them
2672 * to the user. No translation is attempted based on
2673 * byte orientation, nor on code set. I.e it only
2674 * really reads past the wstring and sets the offset
2678 /* The "decoding" is done according to CORBA chapter 15.
2679 * Wstring is not supported for GIOP 1.0.
2683 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2684 int boundary, MessageHeader * header) {
2689 /* CORBA chapter 15:
2690 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2691 * length and string are NUL terminated (length???).
2692 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2696 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2698 /* get length, same for all GIOP versions,
2699 * although for 1.2 CORBA doesnt say, so assume.
2701 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2705 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2706 slength = 5; /* better than core dumping during debug */
2710 if (header->GIOP_version.minor < 2) {
2712 (*offset)++; /* must step past \0 delimiter */
2714 /* assume length is number of characters and not octets, spec not clear */
2715 slength = slength * 2; /* length in octets is 2 * wstring length */
2719 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2721 /* now turn octets (wstring) into something that can be printed by the user */
2722 *seq = make_printable_string(raw_wstring, slength);
2724 g_free(raw_wstring);
2727 return slength; /* return length */
2734 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2736 * typedef short AddressingDisposition;
2737 * const short KeyAddr = 0;
2738 * const short ProfileAddr = 1;
2739 * const short ReferenceAddr = 2;
2740 * struct IORAddressingInfo {
2741 * unsigned long selected_profile_index;
2745 * union TargetAddress switch (AddressingDisposition) {
2746 * case KeyAddr: sequence <octet> object_key;
2747 * case ProfileAddr: IOP::TaggedProfile profile;
2748 * case ReferenceAddr: IORAddressingInfo ior;
2753 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2754 gboolean stream_is_big_endian, guint32 *object_key_len,
2755 gchar **object_key_val)
2757 guint16 discriminant;
2759 gchar *p_object_key;
2764 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2767 proto_tree_add_text (tree, tvb, *offset -2, 2,
2768 "TargetAddress Discriminant: %u", discriminant);
2771 switch (discriminant)
2773 case 0: /* KeyAddr */
2774 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2777 proto_tree_add_text (tree, tvb, *offset -4, 4,
2778 "KeyAddr (object key length): %u", len);
2783 get_CDR_octet_seq(tvb, &object_key, offset, len);
2784 p_object_key = make_printable_string( object_key, len );
2788 proto_tree_add_text (tree, tvb, *offset -len, len,
2789 "KeyAddr (object key): %s", p_object_key);
2791 g_free( p_object_key );
2792 if (object_key_len) {
2793 *object_key_len = len;
2795 if (object_key_val) {
2796 *object_key_val = object_key;
2798 g_free( object_key );
2802 case 1: /* ProfileAddr */
2803 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2804 stream_is_big_endian, NULL);
2806 case 2: /* ReferenceAddr */
2807 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2811 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2812 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2815 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2823 dissect_reply_body (tvbuff_t *tvb, guint offset, packet_info *pinfo,
2824 proto_tree *tree, gboolean stream_is_big_endian,
2825 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2827 guint sequence_length;
2828 gboolean exres = FALSE; /* result of trying explicit dissectors */
2829 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2832 * comp_req_list stuff
2835 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2839 switch (reply_status)
2841 case SYSTEM_EXCEPTION:
2843 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2846 case USER_EXCEPTION:
2848 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2852 proto_tree_add_text(tree, tvb, offset-4, 4,
2853 "Exception length: %u", sequence_length);
2855 if (sequence_length != 0 && sequence_length < ITEM_LABEL_LENGTH)
2859 tvb_ensure_bytes_exist(tvb, offset, sequence_length);
2860 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2862 /* read exception id from buffer and store in*/
2864 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2868 proto_tree_add_string(tree, hf_giop_exception_id, tvb,
2869 offset, sequence_length, header->exception_id);
2875 offset += sequence_length;
2881 * Now just fall through to the NO_EXCEPTION part
2882 * as this is common .
2890 /* lookup MFN in hash directly */
2892 mfn = get_mfn_from_fn(pinfo->fd->num);
2894 if (mfn == pinfo->fd->num)
2895 return; /* no matching frame number, what am I */
2897 /* get entry for this MFN */
2898 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2901 return; /* no matching entry */
2905 * If this packet is a REPLY to a RESOLVE(request)
2907 * TODO - make this lookup faster -- FS
2910 if (!strcmp(giop_op_resolve,entry->operation)) {
2911 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2915 /* TODO -- Put stuff here for other "interesting operations" */
2919 * Call sub dissector.
2920 * First try an find a explicit sub_dissector, then if that
2921 * fails, try the heuristic method.
2926 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
2929 /* Only call heuristic if no explicit dissector was found */
2932 exres = try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
2935 if (!exres && !strcmp(giop_op_is_a, entry->operation) && tree) {
2936 proto_tree_add_text(tree, tvb, offset - 1, 1, "Type Id%s matched",
2937 get_CDR_boolean(tvb, &offset) ? "" : " not");
2941 gint stub_length = tvb_reported_length_remaining(tvb, offset);
2943 proto_tree_add_text(tree, tvb, offset, -1,
2944 "Stub data (%d byte%s)", stub_length,
2945 plurality(stub_length, "", "s"));
2950 case LOCATION_FORWARD:
2951 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2955 case LOCATION_FORWARD_PERM:
2956 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2960 case NEEDS_ADDRESSING_MODE: {
2962 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2964 proto_tree_add_text (tree, tvb, offset -2, 2,
2965 "AddressingDisposition: %u", addr_disp);
2973 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
2979 g_free(repoid); /* free resource */
2989 /* The format of the Reply Header for GIOP 1.0 and 1.1
2990 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
2992 struct ReplyHeader_1_0 {
2993 IOP::ServiceContextList service_context;
2994 unsigned long request_id;
2995 ReplyStatusType_1_0 reply_status;
2999 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3000 MessageHeader * header,
3001 gboolean stream_is_big_endian) {
3005 guint32 reply_status;
3006 proto_tree *reply_tree = NULL;
3008 guint32 mfn; /* matching frame number */
3011 tf = proto_tree_add_text (tree, tvb, offset, -1,
3012 "General Inter-ORB Protocol Reply");
3013 if (reply_tree == NULL)
3015 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3021 * Decode IOP::ServiceContextList
3024 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3026 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3028 if (check_col(pinfo->cinfo, COL_INFO)) {
3029 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3033 proto_tree_add_uint(reply_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
3036 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3038 if (check_col(pinfo->cinfo, COL_INFO)) {
3039 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3040 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3045 proto_tree_add_uint(reply_tree, hf_giop_reply_status, tvb,
3046 offset-4, 4, reply_status);
3051 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3054 if (! pinfo->fd->flags.visited) {
3055 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3056 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3057 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3061 header->req_id = request_id; /* save for sub dissector */
3062 header->rep_status = reply_status; /* save for sub dissector */
3064 /* Do we have a body */
3065 if (tvb_reported_length_remaining(tvb, offset))
3066 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3067 reply_status, header,tree);
3072 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3073 * and 1.1 header, only the fields have been rearranged. From Section
3074 * 15.4.3.1 of the CORBA 2.4 specification:
3076 * struct ReplyHeader_1_2 {
3077 * unsigned long request_id;
3078 * ReplyStatusType_1_2 reply_status;
3079 * IOP:ServiceContextList service_context;
3083 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3085 MessageHeader * header,
3086 gboolean stream_is_big_endian) {
3090 guint32 reply_status;
3091 proto_tree *reply_tree = NULL;
3093 guint32 mfn; /* matching frame number */
3096 tf = proto_tree_add_text (tree, tvb, offset, -1,
3097 "General Inter-ORB Protocol Reply");
3098 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3101 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3103 if (check_col(pinfo->cinfo, COL_INFO)) {
3104 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3108 proto_tree_add_uint (reply_tree, hf_giop_req_id, tvb, offset-4, 4, 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_uint(reply_tree, hf_giop_reply_status, tvb,
3121 offset-4, 4, reply_status);
3125 * Decode IOP::ServiceContextList
3128 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3131 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3134 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3137 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3140 if (! pinfo->fd->flags.visited) {
3141 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3142 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3143 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3148 * Add header to argument list so sub dissector can get header info.
3151 header->req_id = request_id; /* save for sub dissector */
3152 header->rep_status = reply_status; /* save for sub dissector */
3154 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3155 reply_status,header,tree);
3161 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3163 gboolean stream_is_big_endian) {
3167 proto_tree *cancel_request_tree = NULL;
3171 tf = proto_tree_add_text (tree, tvb, offset, -1,
3172 "General Inter-ORB Protocol CancelRequest");
3173 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3176 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3178 if (check_col(pinfo->cinfo, COL_INFO)) {
3179 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3183 proto_tree_add_uint (cancel_request_tree,hf_giop_req_id, tvb, offset-4, 4, request_id);
3189 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3190 * in section 15.4.2.1 of the CORBA 2.4 specification.
3192 * struct RequestHeader{
3193 * IOP::ServiceContextList service_context;
3194 * unsigned long request_id;
3195 * boolean response_expected;
3196 * octet reserved[3]; // Only in GIOP 1.1
3197 * sequence<octet> object_key;
3199 * CORBA::OctetSeq requesting_principal;
3203 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3205 MessageHeader * header, gboolean stream_is_big_endian)
3211 guint32 objkey_len = 0; /* object key length */
3212 gchar *objkey = NULL; /* object key sequence */
3213 gboolean exres = FALSE; /* result of trying explicit dissectors */
3216 gchar *requesting_principal;
3217 gchar *print_requesting_principal;
3218 guint8 response_expected;
3220 proto_tree *request_tree = NULL;
3223 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3228 tf = proto_tree_add_text (tree, tvb, offset, -1,
3229 "General Inter-ORB Protocol Request");
3230 if (request_tree == NULL)
3232 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3240 * Decode IOP::ServiceContextList
3243 decode_ServiceContextList(tvb, request_tree, &offset,stream_is_big_endian, 0);
3246 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3247 if (check_col(pinfo->cinfo, COL_INFO))
3249 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3253 proto_tree_add_uint (request_tree,hf_giop_req_id, tvb, offset-4, 4, request_id);
3256 response_expected = tvb_get_guint8( tvb, offset );
3258 if (check_col(pinfo->cinfo, COL_INFO))
3260 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3261 response_expected ? "two-way" : "one-way");
3265 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3266 "Response expected: %u", response_expected);
3269 if( header->GIOP_version.minor > 0)
3271 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3274 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3275 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3282 /* Length of object_key sequence */
3283 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3288 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3289 /**/ "Object Key length: %u", objkey_len);
3294 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3298 proto_tree_add_item(request_tree, hf_giop_objekt_key, tvb, offset - objkey_len, objkey_len, FALSE);
3305 * Register a cleanup function in case on of our tvbuff accesses
3306 * throws an exception. We need to clean up objkey.
3308 CLEANUP_PUSH(g_free, objkey);
3310 /* length of operation string and string */
3311 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3314 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3315 /**/ "Operation length: %u", len);
3320 if (check_col(pinfo->cinfo, COL_INFO))
3322 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3326 proto_tree_add_string (request_tree, hf_giop_req_operation,tvb, offset - len, len, operation);
3332 * Register a cleanup function in case on of our tvbuff accesses
3333 * throws an exception. We need to clean up operation.
3335 CLEANUP_PUSH(g_free, operation);
3337 /* length of requesting_principal string */
3338 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3341 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3342 /**/ "Requesting Principal Length: %u", len);
3347 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3349 print_requesting_principal = make_printable_string(requesting_principal, len);
3353 proto_tree_add_text (request_tree, tvb, offset - len, len,
3354 /**/ "Requesting Principal: %s", print_requesting_principal);
3358 g_free( print_requesting_principal );
3359 g_free( requesting_principal );
3364 * Save FN,reqid,and operation for later. Add sub_handle later.
3365 * But only if user is NOT clicking.
3368 if (! pinfo->fd->flags.visited)
3369 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3370 request_id,operation,NULL);
3374 * Call subdissector here before freeing "operation" and "key"
3375 * pass request_id also.
3376 * First try an find an explicit sub_dissector, then if that
3377 * fails, try the heuristic method.
3382 header->req_id = request_id; /* save for sub dissector */
3383 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3387 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3390 /* Only call heuristic if no explicit dissector was found */
3393 exres = try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3396 if (!exres && !strcmp(giop_op_is_a, operation) && request_tree) {
3398 len = get_CDR_string(tvb, &type_id, &offset, stream_is_big_endian, 0);
3399 proto_tree_add_text(request_tree, tvb, offset - len - 4, 4,
3400 "Type Id length: %d", len);
3401 proto_tree_add_text(request_tree, tvb, offset - len, len,
3402 "Type Id: %s", type_id);
3406 gint stub_length = tvb_reported_length_remaining(tvb, offset);
3408 proto_tree_add_text(request_tree, tvb, offset, -1,
3409 "Stub data (%d byte%s)", stub_length,
3410 plurality(stub_length, "", "s"));
3414 * We're done with operation, so we can call the cleanup handler to free
3415 * it, and then pop the cleanup handler.
3417 CLEANUP_CALL_AND_POP;
3420 * We're done with objkey, so we can call the cleanup handler to free
3421 * it, and then pop the cleanup handler.
3423 CLEANUP_CALL_AND_POP;
3427 /** The format of a GIOP 1.2 RequestHeader message is
3428 * (CORBA 2.4, sec. 15.4.2):
3430 * struct RequestHeader_1_2 {
3431 * unsigned long request_id;
3432 * octet response_flags;
3433 * octet reserved[3];
3434 * TargetAddress target;
3436 * IOP::ServiceContextList service_context;
3437 * // requesting_principal not in GIOP 1.2
3441 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3443 MessageHeader * header, gboolean stream_is_big_endian)
3448 guint8 response_flags;
3450 gchar *operation = NULL;
3451 proto_tree *request_tree = NULL;
3453 gboolean exres = FALSE; /* result of trying explicit dissectors */
3455 guint32 objkey_len = 0; /* object key length */
3456 gchar *objkey = NULL; /* object key sequence */
3457 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3461 tf = proto_tree_add_text (tree, tvb, offset, -1,
3462 "General Inter-ORB Protocol Request");
3463 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3466 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3467 if (check_col(pinfo->cinfo, COL_INFO))
3469 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3473 proto_tree_add_uint (request_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
3476 response_flags = tvb_get_guint8( tvb, offset );
3480 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3481 "Response flags: %s (%u)",
3482 val_to_str(response_flags, sync_scope, "(0x%x)"),
3486 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3489 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3490 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3494 dissect_target_address(tvb, pinfo, &offset, request_tree, stream_is_big_endian,
3495 &objkey_len, &objkey);
3497 repoid = get_repoid_from_objkey(giop_objkey_hash, objkey, objkey_len);
3501 /* length of operation string */
3502 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3505 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3506 /**/ "Operation length: %u", len);
3511 if (check_col(pinfo->cinfo, COL_INFO))
3513 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3517 proto_tree_add_string (request_tree,hf_giop_req_operation, tvb, offset - len, len, operation);
3524 * Register a cleanup function in case on of our tvbuff accesses
3525 * throws an exception. We need to clean up operation.
3527 CLEANUP_PUSH(g_free, operation);
3530 * Decode IOP::ServiceContextList
3533 decode_ServiceContextList(tvb, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3536 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3537 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3538 * GIOP octet stream start.
3541 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3544 * Save FN,reqid,and operation for later. Add sub_handle later.
3545 * But only if user is NOT clicking.
3548 if (! pinfo->fd->flags.visited)
3549 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3550 request_id,operation,NULL);
3554 * Call sub dissector.
3555 * First try an find a explicit sub_dissector, then if that
3556 * fails, try the heuristic method.
3560 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3563 /* Only call heuristic if no explicit dissector was found */
3566 exres = try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3569 if (!exres && !strcmp(giop_op_is_a, operation) && request_tree) {
3571 len = get_CDR_string(tvb, &type_id, &offset, stream_is_big_endian, 0);
3572 proto_tree_add_text(request_tree, tvb, offset - len - 4, 4,
3573 "Type Id length: %d", len);
3574 proto_tree_add_text(request_tree, tvb, offset - len, len,
3575 "Type Id: %s", type_id);
3579 gint stub_length = tvb_reported_length_remaining(tvb, offset);
3581 proto_tree_add_text(request_tree, tvb, offset, -1,
3582 "Stub data (%d byte%s)", stub_length,
3583 plurality(stub_length, "", "s"));
3587 * We're done with operation, so we can call the cleanup handler to free
3588 * it, and then pop the cleanup handler.
3590 CLEANUP_CALL_AND_POP;
3594 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3595 proto_tree * tree, MessageHeader * header,
3596 gboolean stream_is_big_endian)
3601 proto_tree *locate_request_tree = NULL;
3606 tf = proto_tree_add_text (tree, tvb, offset, -1,
3607 "General Inter-ORB Locate Request");
3608 if (locate_request_tree == NULL)
3610 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3615 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3616 if (check_col(pinfo->cinfo, COL_INFO))
3618 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3620 if (locate_request_tree)
3622 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3623 "Request id: %u", request_id);
3626 if(header->GIOP_version.minor < 2)
3628 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3629 if (locate_request_tree)
3631 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3632 "Object Key length: %u", len);
3637 if(locate_request_tree)
3640 proto_tree_add_item(locate_request_tree, hf_giop_objekt_key, tvb, offset-len, len, FALSE);
3645 else /* GIOP 1.2 and higher */
3647 dissect_target_address(tvb, pinfo, &offset, locate_request_tree,
3648 stream_is_big_endian, NULL, NULL);
3653 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3654 proto_tree * tree, MessageHeader * header,
3655 gboolean stream_is_big_endian)
3659 guint32 locate_status;
3662 proto_tree *locate_reply_tree = NULL;
3667 tf = proto_tree_add_text (tree, tvb, offset, -1,
3668 "General Inter-ORB Locate Reply");
3669 if (locate_reply_tree == NULL)
3671 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3676 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3677 if (check_col(pinfo->cinfo, COL_INFO))
3679 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3681 if (locate_reply_tree)
3683 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3684 "Request id: %u", request_id);
3687 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3688 if (locate_reply_tree)
3690 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3691 "Locate status: %s",
3692 val_to_str(locate_status, giop_locate_status_types, "(0x%x)")
3696 /* Decode the LocateReply body.
3698 * For GIOP 1.0 and 1.1 body immediately follows header.
3699 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3703 if (header->GIOP_version.minor > 1) {
3704 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3708 switch(locate_status) {
3709 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3710 case OBJECT_FORWARD_PERM:
3711 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3713 case LOC_SYSTEM_EXCEPTION:
3714 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3716 case LOC_NEEDS_ADDRESSING_MODE:
3717 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3718 if(locate_reply_tree) {
3719 proto_tree_add_text (tree, tvb, offset -2, 2,
3720 "AddressingDisposition: %u", addr_disp);
3723 default: /* others have no reply body */
3730 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3731 gboolean stream_is_big_endian)
3735 proto_tree *fragment_tree = NULL;
3740 tf = proto_tree_add_text (tree, tvb, offset, -1,
3741 "General Inter-ORB Fragment");
3742 if (fragment_tree == NULL)
3744 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3749 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3750 if (check_col(pinfo->cinfo, COL_INFO))
3752 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3756 proto_tree_add_uint (fragment_tree, hf_giop_req_id, tvb, offset-4, 4,request_id);
3762 /* Main entry point */
3764 static void dissect_giop_common (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3766 MessageHeader header;
3767 tvbuff_t *giop_header_tvb;
3768 tvbuff_t *payload_tvb;
3770 proto_tree *clnp_tree = NULL;
3773 guint minor_version;
3774 gboolean stream_is_big_endian;
3780 giop_dump_collection(cd_module_hash);
3781 giop_dump_collection(cd_objkey_hash);
3782 giop_dump_collection(cd_heuristic_users);
3783 giop_dump_collection(cd_complete_reply_hash);
3784 giop_dump_collection(cd_complete_request_list);
3787 header.exception_id = NULL;
3789 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3790 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3793 * because I have added extra elements in MessageHeader struct
3794 * for sub dissectors. -- FS
3797 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3800 if (check_col (pinfo->cinfo, COL_PROTOCOL))
3802 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3805 if (header.GIOP_version.major != GIOP_MAJOR ||
3806 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3808 /* Bad version number; should we note that and dissect the rest
3809 as data, or should this be done outside dissect_giop_common()
3810 (which is called as the PDU dissector for GIOP-over-TCP,
3811 so it can't return anything), with the test returning FALSE
3812 on the theory that it might have been some other packet that
3813 happened to begin with "GIOP"? We do the former, for now.
3814 If we should return FALSE, we should do so *without* setting
3815 the "Info" column, *without* setting the "Protocol" column,
3816 and *without* adding anything to the protocol tree. */
3818 if (check_col (pinfo->cinfo, COL_INFO))
3820 col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3821 header.GIOP_version.major, header.GIOP_version.minor);
3825 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3826 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3827 proto_tree_add_text (clnp_tree, giop_header_tvb, 0, -1,
3828 "Version %u.%u not supported",
3829 header.GIOP_version.major,
3830 header.GIOP_version.minor);
3832 call_dissector(data_handle,payload_tvb, pinfo, tree);
3836 if (check_col (pinfo->cinfo, COL_INFO))
3838 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3839 header.GIOP_version.major, header.GIOP_version.minor,
3840 val_to_str(header.message_type, giop_message_types,
3841 "Unknown message type (0x%02x)"));
3844 stream_is_big_endian = is_big_endian (&header);
3846 if (stream_is_big_endian)
3847 message_size = pntohl (&header.message_size);
3849 message_size = pletohl (&header.message_size);
3853 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3854 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3855 proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3856 "Magic number: %s", GIOP_MAGIC);
3857 proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3859 header.GIOP_version.major,
3860 header.GIOP_version.minor);
3861 switch (minor_version)
3865 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3866 "Flags: 0x%02x (%s %s)",
3868 (stream_is_big_endian) ? "big-endian" : "little-endian",
3869 (header.flags & 0x02) ? " fragment" : "");
3872 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3873 "Byte ordering: %s-endian",
3874 (stream_is_big_endian) ? "big" : "little");
3878 } /* minor_version */
3880 proto_tree_add_uint_format (clnp_tree,
3881 hf_giop_message_type,
3882 giop_header_tvb, 7, 1,
3883 header.message_type,
3884 "Message type: %s", val_to_str(header.message_type, giop_message_types, "(0x%x)"));
3886 proto_tree_add_uint (clnp_tree,
3887 hf_giop_message_size,
3888 giop_header_tvb, 8, 4, message_size);
3893 if (check_col (pinfo->cinfo, COL_INFO))
3895 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3896 header.GIOP_version.major, header.GIOP_version.minor,
3897 val_to_str(header.message_type, giop_message_types, "(0x%x)"));
3901 switch (header.message_type)
3905 if(header.GIOP_version.minor < 2)
3907 dissect_giop_request_1_1 (payload_tvb, pinfo, tree,
3908 &header, stream_is_big_endian);
3912 dissect_giop_request_1_2 (payload_tvb, pinfo, tree,
3913 &header, stream_is_big_endian);
3920 if(header.GIOP_version.minor < 2)
3922 dissect_giop_reply (payload_tvb, pinfo, tree, &header,
3923 stream_is_big_endian);
3927 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree,
3928 &header, stream_is_big_endian);
3932 dissect_giop_cancel_request(payload_tvb, pinfo, tree,
3933 stream_is_big_endian);
3936 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
3937 stream_is_big_endian);
3940 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
3941 stream_is_big_endian);
3944 dissect_giop_fragment(payload_tvb, pinfo, tree,
3945 stream_is_big_endian);
3950 } /* switch message_type */
3954 * XXX - we should catch exceptions here, so that we can free
3955 * this if an exception is thrown.
3956 * We'd then have to forward the exception.
3958 if (header.exception_id != NULL)
3959 g_free(header.exception_id);
3963 get_giop_pdu_len(tvbuff_t *tvb, int offset)
3966 MessageHeader header;
3968 gboolean stream_is_big_endian;
3970 tvb_memcpy (tvb, (guint8 *)&header, offset, GIOP_HEADER_SIZE );
3972 stream_is_big_endian = is_big_endian (&header);
3974 if (stream_is_big_endian)
3975 message_size = pntohl (&header.message_size);
3977 message_size = pletohl (&header.message_size);
3980 return message_size + GIOP_HEADER_SIZE;
3984 dissect_giop_tcp (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3985 tcp_dissect_pdus(tvb, pinfo, tree, giop_desegment, GIOP_HEADER_SIZE,
3986 get_giop_pdu_len, dissect_giop_common);
3990 dissect_giop_heur (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3994 conversation_t *conversation;
3995 /* check magic number and version */
3998 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
4000 tot_len = tvb_length_remaining(tvb, 0);
4002 if (tot_len < GIOP_HEADER_SIZE) /* tot_len < 12 */
4004 /* Not enough data captured to hold the GIOP header; don't try
4005 to interpret it as GIOP. */
4008 if ( tvb_memeql(tvb, 0, GIOP_MAGIC ,4) != 0)
4011 if ( pinfo->ptype == PT_TCP )
4014 * Make the GIOP dissector the dissector for this conversation.
4016 * If this isn't the first time this packet has been processed,
4017 * we've already done this work, so we don't need to do it
4020 if (!pinfo->fd->flags.visited)
4022 conversation = find_conversation(pinfo->fd->num, &pinfo->src,
4023 &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4024 if (conversation == NULL)
4026 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
4027 &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4030 conversation_set_dissector(conversation, giop_tcp_handle);
4032 dissect_giop_tcp (tvb, pinfo, tree);
4036 dissect_giop_common (tvb, pinfo, tree);
4044 proto_register_giop (void)
4046 static hf_register_info hf[] = {
4047 { &hf_giop_message_type,
4048 { "Message type", "giop.type",
4049 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4052 { &hf_giop_message_size,
4053 { "Message size", "giop.len",
4054 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4058 { "Repository ID", "giop.repoid",
4059 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4062 { &hf_giop_string_length,
4063 { "String Length", "giop.strlen",
4064 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4067 { &hf_giop_sequence_length,
4068 { "Sequence Length", "giop.seqlen",
4069 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4072 { &hf_giop_profile_id,
4073 { "Profile ID", "giop.profid",
4074 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
4079 { "IOR::type_id", "giop.typeid",
4080 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4083 { &hf_giop_iiop_v_maj,
4084 { "IIOP Major Version", "giop.iiop_vmaj",
4085 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4088 { &hf_giop_iiop_v_min,
4089 { "IIOP Minor Version", "giop.iiop_vmin",
4090 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4093 { &hf_giop_endianess,
4094 { "Endianess", "giop.endianess",
4095 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4098 { &hf_giop_IIOP_tag,
4099 { "IIOP Component TAG", "giop.iioptag",
4100 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4104 { "IOR Profile TAG", "giop.iortag",
4105 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4109 { "TypeCode enum", "giop.TCKind",
4110 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4113 { &hf_giop_typecode_count,
4114 { "TypeCode count", "giop.tccount",
4115 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4118 { &hf_giop_typecode_default_used,
4119 { "default_used", "giop.tcdefault_used",
4120 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4123 { &hf_giop_typecode_digits,
4124 { "Digits", "giop.tcdigits",
4125 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4129 { &hf_giop_typecode_length,
4130 { "Length", "giop.tclength",
4131 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4134 { &hf_giop_typecode_max_length,
4135 { "Maximum length", "giop.tcmaxlen",
4136 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4139 { &hf_giop_typecode_member_name,
4140 { "TypeCode member name", "giop.tcmemname",
4141 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4144 { &hf_giop_typecode_name,
4145 { "TypeCode name", "giop.tcname",
4146 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4149 { &hf_giop_typecode_scale,
4150 { "Scale", "giop.tcscale",
4151 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4154 { &hf_giop_typecode_ValueModifier,
4155 { "ValueModifier", "giop.tcValueModifier",
4156 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4159 { &hf_giop_typecode_Visibility,
4160 { "Visibility", "giop.tcVisibility",
4161 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4166 { &hf_giop_type_boolean,
4167 { "TypeCode boolean data", "giop.tcboolean",
4168 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4171 { &hf_giop_type_char,
4172 { "TypeCode char data", "giop.tcchar",
4173 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4176 { &hf_giop_type_double,
4177 { "TypeCode double data", "giop.tcdouble",
4178 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4181 { &hf_giop_type_enum,
4182 { "TypeCode enum data", "giop.tcenumdata",
4183 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4187 * float as double ?? -- FIX
4190 { &hf_giop_type_float,
4191 { "TypeCode float data", "giop.tcfloat",
4192 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4195 { &hf_giop_type_long,
4196 { "TypeCode long data", "giop.tclongdata",
4197 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4200 { &hf_giop_type_octet,
4201 { "TypeCode octet data", "giop.tcoctet",
4202 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4205 { &hf_giop_type_short,
4206 { "TypeCode short data", "giop.tcshortdata",
4207 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4210 { &hf_giop_type_string,
4211 { "TypeCode string data", "giop.tcstring",
4212 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4215 { &hf_giop_type_ulong,
4216 { "TypeCode ulong data", "giop.tculongdata",
4217 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4220 { &hf_giop_type_ushort,
4221 { "TypeCode ushort data", "giop.tcushortdata",
4222 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4226 * IIOP Module - Chapter 15.10.2
4229 { &hf_giop_iiop_host,
4230 { "IIOP::Profile_host", "giop.iiop.host",
4231 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4235 { &hf_giop_iiop_port,
4236 { "IIOP::Profile_port", "giop.iiop.port",
4237 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4242 * IIOP ServiceContext
4245 { &hf_giop_iop_vscid,
4246 { "VSCID", "giop.iiop.vscid",
4247 FT_UINT32, BASE_HEX, NULL, 0xffffff00, "", HFILL }
4251 { &hf_giop_iop_scid,
4252 { "SCID", "giop.iiop.scid",
4253 FT_UINT32, BASE_HEX, NULL, 0x000000ff, "", HFILL }
4258 { "Request id", "giop.request_id",
4259 FT_UINT32, BASE_DEC, NULL, 0, "", HFILL }
4262 { &hf_giop_req_operation,
4263 { "Request operation", "giop.request_op",
4264 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4266 { &hf_giop_reply_status,
4267 { "Reply status", "giop.replystatus",
4268 FT_UINT32, BASE_DEC, VALS(reply_status_types), 0x0, "", HFILL }
4270 { &hf_giop_exception_id,
4271 { "Exception id", "giop.exceptionid",
4272 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4274 { &hf_giop_objekt_key,
4275 { "Object Key", "giop.objektkey",
4276 FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
4283 static gint *ett[] = {
4287 &ett_giop_cancel_request,
4288 &ett_giop_locate_request,
4289 &ett_giop_locate_reply,
4296 module_t *giop_module;
4298 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4300 proto_register_field_array (proto_giop, hf, array_length (hf));
4301 proto_register_subtree_array (ett, array_length (ett));
4304 /* register init routine */
4306 register_init_routine( &giop_init); /* any init stuff */
4308 /* register preferences */
4309 giop_module = prefs_register_protocol(proto_giop, NULL);
4310 prefs_register_bool_preference(giop_module, "desegment_giop_messages",
4311 "Reassemble GIOP messages spanning multiple TCP segments",
4312 "Whether the GIOP dissector should reassemble messages spanning multiple TCP segments."
4313 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4317 * Init the giop user module hash tables here, as giop users
4318 * will populate it via register_giop_user_module BEFORE my
4319 * own giop_init() is called.
4322 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4328 void proto_reg_handoff_giop (void) {
4329 data_handle = find_dissector("data");
4330 giop_tcp_handle = create_dissector_handle(dissect_giop_tcp, proto_giop);
4331 heur_dissector_add("tcp", dissect_giop_heur, proto_giop);
4332 /* Support DIOP (GIOP/UDP) */
4333 heur_dissector_add("udp", dissect_giop_heur, proto_giop);
4334 /* Port will be set by conversation */
4335 dissector_add("tcp.port", 0, giop_tcp_handle);
4344 * Ref Corba v2.4.2 Chapter 13
4352 typedef unsigned long ProfileId;
4354 const ProfileId TAG_INTERNET_IOP = 0;
4355 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4357 struct TaggedProfile {
4359 sequence <octet> profile_data;
4364 sequence <TaggedProfile> profiles;
4367 typedef unsigned long ComponentId;
4369 struct TaggedComponent {
4371 sequence <octet> component_data;
4374 typedef sequence <TaggedComponent> MultipleComponentProfile;
4380 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4381 guint32 boundary, gboolean stream_is_big_endian) {
4384 guint32 seqlen_p; /* sequence length of profiles */
4387 proto_tree *tree = NULL; /* IOR tree */
4390 gchar *repobuf; /* for repository ID */
4394 /* create a subtree */
4397 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
4398 tree = proto_item_add_subtree (tf, ett_giop_ior);
4402 /* Get type_id == Repository ID */
4404 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4407 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4408 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4410 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4411 *offset-u_octet4,u_octet4,repobuf);
4416 * Register a cleanup function in case on of our tvbuff accesses
4417 * throws an exception. We need to clean up repobuf.
4418 * We can't free it yet, as we must wait until we have the object
4419 * key, as we have to add both to the hash table.
4421 CLEANUP_PUSH(g_free, repobuf);
4423 /* Now get a sequence of profiles */
4424 /* Get sequence length (number of elements) */
4426 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4428 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4429 *offset-sizeof(seqlen_p),4,seqlen_p);
4433 /* fetch all TaggedProfiles in this sequence */
4435 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4436 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4440 * We're done with repobuf, so we can call the cleanup handler to free
4441 * it, and then pop the cleanup handler.
4443 CLEANUP_CALL_AND_POP;
4447 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4448 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4450 guint32 seqlen_pd; /* sequence length of profile data */
4452 guint32 pidtag; /* profile ID TAG */
4454 gchar *profile_data; /* profile_data pointer */
4455 gchar *p_profile_data; /* printable profile_data pointer */
4457 guint32 new_boundary; /* for encapsulations encountered */
4458 gboolean new_big_endianess; /* for encapsulations encountered */
4460 /* Get ProfileId tag */
4462 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4465 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4466 *offset-sizeof(pidtag),4,pidtag);
4469 /* get sequence length, new endianness and boundary for encapsulation */
4471 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4472 stream_is_big_endian, boundary,
4473 &new_big_endianess, &new_boundary);
4475 /* return if zero length sequence */
4482 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4483 * decode it, otherwise just dump the octet sequence
4485 * also, store IOR in our objectkey hash
4487 * TODO - handle other TAGS
4491 case IOP_TAG_INTERNET_IOP:
4493 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4498 /* fetch all octets in this sequence , but skip endianess */
4500 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4502 /* Make a printable string */
4504 p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4507 proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4508 "Profile Data: %s", p_profile_data);
4511 g_free(p_profile_data);
4513 g_free(profile_data);
4524 * Decode IIOP IOR Profile
4525 * Ref Chap 15.7.2 in Corba Spec
4529 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4530 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4531 gboolean store_flag) {
4533 guint32 i; /* loop index */
4535 guint8 v_major,v_minor; /* IIOP version */
4537 guint32 u_octet4; /* u long */
4538 guint16 u_octet2; /* u short */
4539 guint32 seqlen; /* generic sequence length */
4540 guint32 seqlen1; /* generic sequence length */
4541 gchar *objkey; /* object key pointer */
4542 gchar *p_chars; /* printable characters pointer */
4545 /* Get major/minor version */
4547 v_major = get_CDR_octet(tvb,offset);
4548 v_minor = get_CDR_octet(tvb,offset);
4552 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4553 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4554 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4555 *offset-sizeof(v_minor),1,v_minor );
4561 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4564 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4565 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4567 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4568 *offset-u_octet4,u_octet4,buf);
4572 g_free(buf); /* dont forget */
4576 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4579 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4580 *offset-sizeof(u_octet2),2,u_octet2);
4584 /* Object Key - sequence<octet> object_key */
4586 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4589 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4590 *offset-sizeof(seqlen),4,seqlen);
4594 /* fetch all octets in this sequence */
4595 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4598 * Now we may have the Repository ID from earlier, as well
4599 * as the object key sequence and lengh. So lets store them in
4600 * our objectkey hash and free buffers.
4602 * But only insert if user is not clicking and repo id not NULL.
4608 if(!pinfo->fd->flags.visited)
4609 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4614 * No pinfo, but store anyway if flag set. eg: IOR read from file
4618 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4623 proto_tree_add_item(tree, hf_giop_objekt_key, tvb, *offset -seqlen, seqlen, FALSE);
4629 * Now see if if its v1.1 or 1.2, as they can contain
4630 * extra sequence of IOP::TaggedComponents
4643 /* sequence of IOP::TaggedComponents */
4644 /* Ref Chap 13 in Corba Spec */
4646 /* get sequence length */
4647 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4650 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4651 *offset-sizeof(seqlen),4,seqlen);
4654 for (i=0; i< seqlen; i++) {
4656 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4658 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4659 *offset-sizeof(u_octet4),4,u_octet4);
4662 /* get component_data */
4663 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4665 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4666 *offset-sizeof(seqlen1),4,seqlen1);
4670 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4673 /* Make a printable string of data */
4675 p_chars = make_printable_string(buf, seqlen1);
4677 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4678 "component_data: %s", p_chars);
4692 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4699 * From Section 13.10.2.5 of the CORBA 3.0 spec.
4701 * module CONV_FRAME {
4702 * typedef unsigned long CodeSetId;
4703 * struct CodeSetContext {
4704 * CodeSetId char_data;
4705 * CodeSetId wchar_data;
4709 * Code sets are identified by a 32-bit integer id from OSF.
4710 * See: ftp://ftp.opengroup.org/pub/code_set_registry
4712 static void decode_CodeSets(tvbuff_t *tvb, proto_tree *tree, int *offset,
4713 gboolean stream_is_be, guint32 boundary) {
4715 /* The boundary being passed in is the offset where the context_data
4716 * sequence begins. */
4718 guint32 code_set_id;
4720 /* We pass in -boundary, because the alignment is calculated relative to
4721 the beginning of the context_data sequence.
4722 Inside get_CDR_ulong(), the calculation will be (offset +(- boundary)) % 4
4723 to determine the correct alignment of the short. */
4724 code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
4726 proto_tree_add_text (tree, tvb, *offset - 4, 4,
4727 "char_data: 0x%08x", code_set_id);
4729 code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
4731 proto_tree_add_text (tree, tvb, *offset - 4, 4,
4732 "wchar_data: 0x%08x", code_set_id);
4738 * From Section 2.7.3 of the Real-time CORBA 1.1 Standard, the CORBA priority
4739 * is represented in the GIOP service request as:
4742 * typedef short ServiceId;
4743 * const ServiceId RTCorbaPriority = 10;
4746 * The RT-CORBA priority is a CDR encoded short value in a sequence<octet>
4749 static void decode_RTCorbaPriority(tvbuff_t *tvb, proto_tree *tree, int *offset,
4750 gboolean stream_is_be, guint32 boundary) {
4752 /* The boundary being passed in is the offset where the context_data
4753 * sequence begins. */
4757 /* RTCorbaPriority is stored as a CDR encoded short */
4758 /* We pass in -boundary, because the alignment is calculated relative to
4759 the beginning of the context_data sequence.
4760 Inside get_CDR_short(), the calculation will be (offset + (- boundary)) % 2
4761 to determine the correct alignment of the short. */
4762 rtpriority = get_CDR_short(tvb, offset, stream_is_be, -((gint32) boundary) );
4765 /* Highlight all of context_data except for the first endian byte */
4766 proto_tree_add_text (tree, tvb, *offset - 2, 2,
4767 "RTCorbaPriority: %d", rtpriority);
4772 static void decode_UnknownServiceContext(tvbuff_t *tvb, proto_tree *tree, int *offset,
4773 gboolean stream_is_be, guint32 boundary) {
4775 guint32 context_data_len;
4776 gchar *p_context_data;
4777 gchar *context_data;
4779 /* get sequence length, and NO encapsulation */
4780 context_data_len = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4783 /* return if zero length sequence */
4784 if(context_data_len == 0)
4788 * Now decode sequence according to vendor ServiceId, but I dont
4789 * have that yet, so just dump it as data.
4792 /* fetch all octets in this sequence */
4794 get_CDR_octet_seq(tvb, &context_data, offset, context_data_len);
4796 /* Make a printable string */
4798 p_context_data = make_printable_string( context_data, context_data_len );
4801 proto_tree_add_text (tree, tvb, *offset - context_data_len , context_data_len,
4802 "context_data: %s", p_context_data);
4805 g_free(context_data);
4806 g_free(p_context_data);
4814 * typedef unsigned long ServiceID;
4816 * struct ServiceContext {
4817 * ServiceID context_id;
4818 * sequence <octet> context_data;
4820 * typedef sequence <ServiceContext> ServiceContextList;
4823 * Note: Spec says context_data is an encapsulation.
4828 void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *ptree, int *offset,
4829 gboolean stream_is_be, guint32 boundary) {
4831 guint32 seqlen; /* sequence length */
4832 guint32 context_data_len; /* context data sequence length */
4834 proto_tree *tree = NULL; /* ServiceContext tree */
4835 proto_tree *sub_tree1 = NULL;
4836 proto_item *tf = NULL, *tf_st1;
4841 guint32 vscid; /* Vendor Service context id */
4843 const gchar *service_context_name;
4844 gboolean encapsulation_is_be;
4845 guint32 encapsulation_boundary;
4846 int temp_offset, temp_offset1;
4847 int start_offset = *offset;
4849 /* create a subtree */
4852 /* set length to 0 now and correct with proto_item_set_len() later */
4853 tf = proto_tree_add_text (ptree, tvb, *offset, 0, "ServiceContextList");
4855 tree = proto_item_add_subtree (tf, ett_giop_scl);
4858 /* Get sequence length (number of elements) */
4859 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4862 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4863 *offset-sizeof(seqlen),4,seqlen);
4866 /* return if zero length sequence */
4870 if (*offset - start_offset <= 0)
4871 THROW(ReportedBoundsError);
4872 proto_item_set_len(tf, *offset - start_offset);
4878 /* Loop for all ServiceContext's */
4880 for (i=0; i<seqlen; i++) {
4882 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4883 vscid = (context_id & 0xffffff00) >> 8; /* vendor info, top 24 bits */
4884 scid = context_id & 0x000000ff; /* standard service info, lower 8 bits */
4887 proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4888 *offset-sizeof(guint32),4,vscid);
4890 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4891 *offset-sizeof(guint32),4,scid);
4895 if( vscid == 0) { /* OMG specified */
4896 service_context_name = val_to_str(scid, service_context_ids, "(0x%x)");
4897 } else { /* Proprietary vscid */
4898 service_context_name = "Unknown";
4902 proto_tree_add_text (tree, tvb, *offset -sizeof(context_id), 4,
4903 "Service Context ID: %s (%u)", service_context_name,
4907 temp_offset1 = *offset;
4908 /* The OMG has vscid of 0 reserved */
4909 if( vscid != 0 || scid > max_service_context_id ) {
4910 decode_UnknownServiceContext(tvb, tree, offset, stream_is_be, boundary);
4914 temp_offset = *offset;
4915 /* get sequence length, new endianness and boundary for encapsulation */
4916 context_data_len = get_CDR_encap_info(tvb, sub_tree1, offset,
4917 stream_is_be, boundary,
4918 &encapsulation_is_be , &encapsulation_boundary);
4921 tf_st1 = proto_tree_add_text (tree, tvb, temp_offset, sizeof(context_data_len) + context_data_len , service_context_name);
4922 sub_tree1 = proto_item_add_subtree (tf_st1, ett_giop_scl_st1);
4925 if (context_data_len == 0)
4928 /* See CORBA 3.0.2 standard, section Section 15.3.3 "Encapsulation",
4929 * for how CDR types can be marshalled into a sequence<octet>.
4930 * The first octet in the sequence determines endian order,
4931 * 0 == big-endian, 1 == little-endian
4936 case 0x01: /* Codesets */
4937 decode_CodeSets(tvb, sub_tree1, offset,
4938 encapsulation_is_be, encapsulation_boundary);
4940 case 0x0a: /* RTCorbaPriority */
4941 decode_RTCorbaPriority(tvb, sub_tree1, offset,
4942 encapsulation_is_be, encapsulation_boundary);
4946 /* Need to fill these in as we learn them */
4947 *offset = temp_offset1;
4948 decode_UnknownServiceContext(tvb, sub_tree1, offset, stream_is_be,
4952 /* Set the offset to the end of the context_data sequence */
4953 *offset = temp_offset1 + sizeof(context_data_len) + context_data_len;
4958 if (*offset - start_offset <= 0)
4959 THROW(ReportedBoundsError);
4960 proto_item_set_len(tf, *offset - start_offset);
4965 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
4968 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
4969 gboolean stream_is_big_endian,
4972 guint32 length; /* string length */
4973 guint32 minor_code_value;
4974 guint32 completion_status;
4976 gchar *buf; /* pointer to string buffer */
4978 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
4981 proto_tree_add_text(tree, tvb, *offset-4, 4,
4982 "Exception length: %u", length);
4984 proto_tree_add_text(tree, tvb, *offset - length, length,
4985 "Exception id: %s", buf );
4990 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4991 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4994 proto_tree_add_text(tree, tvb, *offset-8, 4,
4995 "Minor code value: %u", minor_code_value);
4996 proto_tree_add_text(tree, tvb, *offset-4, 4,
4997 "Completion Status: %u", completion_status);
5003 * Helper functions for dissecting TypeCodes
5005 * These functions decode the complex parameter lists
5006 * of TypeCodes as defined in the CORBA spec chapter 15.
5009 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5010 gboolean stream_is_big_endian, guint32 boundary) {
5012 guint32 new_boundary; /* new boundary for encapsulation */
5013 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5015 guint32 seqlen; /* sequence length */
5017 /* get sequence length, new endianness and boundary for encapsulation */
5018 seqlen = get_CDR_encap_info(tvb, tree, offset,
5019 stream_is_big_endian, boundary,
5020 &new_stream_is_big_endian, &new_boundary);
5022 /* get repository ID */
5023 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5027 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5028 hf_giop_typecode_name);
5033 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5034 gboolean stream_is_big_endian, guint32 boundary,
5035 MessageHeader * header ) {
5037 guint32 new_boundary; /* new boundary for encapsulation */
5038 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5040 guint32 count; /* parameter count (of tuples) */
5041 guint32 seqlen; /* sequence length */
5042 guint32 i; /* loop index */
5044 /* get sequence lengt,h new endianness and boundary for encapsulation */
5045 seqlen = get_CDR_encap_info(tvb, tree, offset,
5046 stream_is_big_endian, boundary,
5047 &new_stream_is_big_endian, &new_boundary);
5049 /* get repository ID */
5050 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5054 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5055 hf_giop_typecode_name);
5057 /* get count of tuples */
5058 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5060 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5061 *offset-sizeof(count),4,count);
5064 /* get all tuples */
5065 for (i=0; i< count; i++) {
5066 /* get member name */
5067 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5068 hf_giop_typecode_member_name);
5070 /* get member type */
5071 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5077 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5078 gboolean stream_is_big_endian, guint32 boundary,
5079 MessageHeader * header) {
5081 guint32 new_boundary; /* new boundary for encapsulation */
5082 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5084 guint32 TCKind; /* TypeCode */
5085 gint32 s_octet4; /* signed int32 */
5087 guint32 count; /* parameter count (of tuples) */
5088 guint32 seqlen; /* sequence length */
5089 guint32 i; /* loop index */
5091 /* get sequence legnth, new endianness and boundary for encapsulation */
5092 seqlen = get_CDR_encap_info(tvb, tree, offset,
5093 stream_is_big_endian, boundary,
5094 &new_stream_is_big_endian, &new_boundary);
5096 /* get repository ID */
5097 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5101 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5102 hf_giop_typecode_name);
5104 /* get discriminant type */
5105 TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5107 /* get default used */
5108 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
5110 proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
5111 *offset-sizeof(s_octet4),4,s_octet4);
5113 /* get count of tuples */
5114 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5116 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5117 *offset-sizeof(count),4,count);
5120 /* get all tuples */
5121 for (i=0; i< count; i++) {
5122 /* get label value, based on TCKind above */
5123 dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
5125 /* get member name */
5126 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5127 hf_giop_typecode_member_name);
5129 /* get member type */
5130 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5136 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5137 gboolean stream_is_big_endian, guint32 boundary) {
5139 guint32 new_boundary; /* new boundary for encapsulation */
5140 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5142 guint32 count; /* parameter count (of tuples) */
5143 guint32 seqlen; /* sequence length */
5144 guint32 i; /* loop index */
5146 /* get sequence length, new endianness and boundary for encapsulation */
5147 seqlen = get_CDR_encap_info(tvb, tree, offset,
5148 stream_is_big_endian, boundary,
5149 &new_stream_is_big_endian, &new_boundary);
5151 /* get repository ID */
5152 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5156 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5157 hf_giop_typecode_name);
5159 /* get count of tuples */
5160 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5162 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5163 *offset-sizeof(count),4,count);
5166 /* get all tuples */
5167 for (i=0; i< count; i++) {
5168 /* get member name */
5169 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5170 hf_giop_typecode_member_name);
5176 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5177 gboolean stream_is_big_endian, guint32 boundary,
5178 MessageHeader * header) {
5180 guint32 new_boundary; /* new boundary for encapsulation */
5181 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5183 guint32 u_octet4; /* unsigned int32 */
5185 guint32 seqlen; /* sequence length */
5187 /* get sequence length, new endianness and boundary for encapsulation */
5188 seqlen = get_CDR_encap_info(tvb, tree, offset,
5189 stream_is_big_endian, boundary,
5190 &new_stream_is_big_endian, &new_boundary);
5192 /* get element type */
5193 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5195 /* get max length */
5196 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5198 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
5199 *offset-sizeof(u_octet4),4,u_octet4);
5204 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5205 gboolean stream_is_big_endian, guint32 boundary,
5206 MessageHeader * header) {
5208 guint32 new_boundary; /* new boundary for encapsulation */
5209 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5211 guint32 u_octet4; /* unsigned int32 */
5213 guint32 seqlen; /* sequence length */
5215 /* get sequence length, new endianness and boundary for encapsulation */
5216 seqlen = get_CDR_encap_info(tvb, tree, offset,
5217 stream_is_big_endian, boundary,
5218 &new_stream_is_big_endian, &new_boundary);
5220 /* get element type */
5221 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5224 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5226 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5227 *offset-sizeof(u_octet4),4,u_octet4);
5232 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5233 gboolean stream_is_big_endian, guint32 boundary,
5234 MessageHeader * header) {
5236 guint32 new_boundary; /* new boundary for encapsulation */
5237 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5239 guint32 seqlen; /* sequence length */
5241 /* get sequence legnth, new endianness and boundary for encapsulation */
5242 seqlen = get_CDR_encap_info(tvb, tree, offset,
5243 stream_is_big_endian, boundary,
5244 &new_stream_is_big_endian, &new_boundary);
5246 /* get repository ID */
5247 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5251 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5252 hf_giop_typecode_name);
5254 /* get ??? (noname) TypeCode */
5255 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5260 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5261 gboolean stream_is_big_endian, guint32 boundary,
5262 MessageHeader * header) {
5264 guint32 new_boundary; /* new boundary for encapsulation */
5265 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5267 guint32 count; /* parameter count (of tuples) */
5268 guint32 seqlen; /* sequence length */
5269 guint32 i; /* loop index */
5271 /* get sequence length, new endianness and boundary for encapsulation */
5272 seqlen = get_CDR_encap_info(tvb, tree, offset,
5273 stream_is_big_endian, boundary,
5274 &new_stream_is_big_endian, &new_boundary);
5276 /* get repository ID */
5277 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5281 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5282 hf_giop_typecode_name);
5284 /* get count of tuples */
5285 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5287 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5288 *offset-sizeof(count),4,count);
5291 /* get all tuples */
5292 for (i=0; i< count; i++) {
5293 /* get member name */
5294 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5295 hf_giop_typecode_member_name);
5297 /* get member type */
5298 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5304 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5305 gboolean stream_is_big_endian, guint32 boundary,
5306 MessageHeader * header) {
5308 guint32 new_boundary; /* new boundary for encapsulation */
5309 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5311 gint16 s_octet2; /* signed int16 */
5313 guint32 count; /* parameter count (of tuples) */
5314 guint32 seqlen; /* sequence length */
5315 guint32 i; /* loop index */
5317 /* get sequence length, new endianness and boundary for encapsulation */
5318 seqlen = get_CDR_encap_info(tvb, tree, offset,
5319 stream_is_big_endian, boundary,
5320 &new_stream_is_big_endian, &new_boundary);
5322 /* get repository ID */
5323 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5327 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5328 hf_giop_typecode_name);
5330 /* get ValueModifier */
5331 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5333 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5334 *offset-sizeof(s_octet2),2,s_octet2);
5337 /* get conrete base */
5338 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5340 /* get count of tuples */
5341 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5343 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5344 *offset-sizeof(count),4,count);
5347 /* get all tuples */
5348 for (i=0; i< count; i++) {
5349 /* get member name */
5350 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5351 hf_giop_typecode_member_name);
5353 /* get member type */
5354 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5356 /* get Visibility */
5357 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5359 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5360 *offset-sizeof(s_octet2),2,s_octet2);
5367 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5368 gboolean stream_is_big_endian, guint32 boundary,
5369 MessageHeader * header) {
5371 guint32 new_boundary; /* new boundary for encapsulation */
5372 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5374 guint32 seqlen; /* sequence length */
5376 /* get sequence length, new endianness and boundary for encapsulation */
5377 seqlen = get_CDR_encap_info(tvb, tree, offset,
5378 stream_is_big_endian, boundary,
5379 &new_stream_is_big_endian, &new_boundary);
5381 /* get repository ID */
5382 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5386 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5387 hf_giop_typecode_name);
5389 /* get ??? (noname) TypeCode */
5390 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5394 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5395 gboolean stream_is_big_endian, guint32 boundary) {
5397 guint32 new_boundary; /* new boundary for encapsulation */
5398 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5400 guint32 seqlen; /* sequence length */
5402 /* get sequence length, new endianness and boundary for encapsulation */
5403 seqlen = get_CDR_encap_info(tvb, tree, offset,
5404 stream_is_big_endian, boundary,
5405 &new_stream_is_big_endian, &new_boundary);
5407 /* get repository ID */
5408 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5412 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5413 hf_giop_typecode_name);
5418 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5419 gboolean stream_is_big_endian, guint32 boundary) {
5421 guint32 new_boundary; /* new boundary for encapsulation */
5422 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5424 guint32 seqlen; /* sequence length */
5426 /* get sequence length, new endianness and boundary for encapsulation */
5427 seqlen = get_CDR_encap_info(tvb, tree, offset,
5428 stream_is_big_endian, boundary,
5429 &new_stream_is_big_endian, &new_boundary);
5431 /* get repository ID */
5432 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5436 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5437 hf_giop_typecode_name);
5441 /* Typecode parameter lists are encoded as encapsulations and
5442 * this function gets the encapsulation information; see
5443 * CORBA spec chapter 15
5446 * Renamed to get_CDR_encap_info() for any encapsulation
5447 * we come across, useful helper function
5449 * Also, should return immediately if seqlen == 0.
5450 * ie: Forget about trying to grab endianess for
5451 * zero length sequence.
5453 * Caller must always check seqlen == 0, and not assume its value
5456 * Note: there seemed to be considerable confusion in corba
5457 * circles as to the correct interpretation of encapsulations,
5458 * and zero length sequences etc, but this is our best bet at the
5465 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5466 gboolean old_stream_is_big_endian, guint32 old_boundary,
5467 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5469 guint32 seqlen; /* sequence length */
5470 guint8 giop_endianess;
5472 /* Get sequence length of parameter list */
5473 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5475 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5476 *offset-sizeof(seqlen),4,seqlen);
5482 * seqlen == 0, implies no endianess and no data
5483 * so just return. Populate new_boundary_ptr and
5484 * new_stream_is_big_endian_ptr with current (old)
5485 * values, just to keep everyone happy. -- FS
5491 *new_boundary_ptr = old_boundary;
5492 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5498 /* Start of encapsulation of parameter list */
5499 *new_boundary_ptr = *offset; /* remember */
5500 giop_endianess = get_CDR_octet(tvb,offset);
5502 *new_stream_is_big_endian_ptr = ! giop_endianess;
5505 * Glib: typedef gint gboolean;
5506 * ie: It is not a guint8, so cannot use sizeof to correctly
5512 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5513 *offset-1,1,giop_endianess);
5523 * gets a TypeCode complex string parameter and
5524 * displays it in the relevant tree.
5527 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5528 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5530 guint32 u_octet4; /* unsigned int32 */
5531 gchar *buf; /* ptr to string buffer */
5534 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5537 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5538 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5540 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5544 g_free(buf); /* dont forget */
5549 * For a given data type, given by a TypeCode gets the associated data
5550 * and displays it in the relevant tree.
5553 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5554 gboolean stream_is_big_endian, guint32 boundary,
5555 MessageHeader * header, guint32 data_type ) {
5557 gboolean my_boolean; /* boolean */
5559 gint8 s_octet1; /* signed int8 */
5560 guint8 u_octet1; /* unsigned int8 */
5562 gint16 s_octet2; /* signed int16 */
5563 guint16 u_octet2; /* unsigned int16 */
5565 gint32 s_octet4; /* signed int32 */
5566 guint32 u_octet4; /* unsigned int32 */
5568 gdouble my_double; /* double */
5569 gfloat my_float; /* float */
5571 gchar *buf = NULL; /* ptr to string buffer */
5573 /* Grab the data according to data type */
5575 switch (data_type) {
5577 /* nothing to decode */
5580 /* nothing to decode */
5583 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5585 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5586 *offset-sizeof(s_octet2),2,s_octet2);
5590 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5592 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5593 *offset-sizeof(s_octet4),4,s_octet4);
5597 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5599 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5600 *offset-sizeof(u_octet2),2,u_octet2);
5604 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5606 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5607 *offset-sizeof(u_octet4),4,u_octet4);
5611 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5613 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5614 *offset-sizeof(my_float),4,my_float);
5618 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5620 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5621 *offset-sizeof(my_double),8,my_double);
5625 my_boolean = get_CDR_boolean(tvb,offset);
5627 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5628 *offset-1,1,my_boolean);
5632 u_octet1 = get_CDR_char(tvb,offset);
5634 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5635 *offset-sizeof(u_octet1),1,u_octet1);
5639 u_octet1 = get_CDR_octet(tvb,offset);
5641 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5642 *offset-sizeof(u_octet1),1,u_octet1);
5646 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5649 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5660 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5662 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5663 *offset-sizeof(u_octet4),4,u_octet4);
5667 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5669 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5670 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5672 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5673 *offset-u_octet4,u_octet4,buf);
5677 g_free(buf); /* dont forget */
5694 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5697 * XXX - can any of these throw an exception?
5698 * If so, we need to catch the exception and free "buf".
5700 if (s_octet1 < 0) { /* no size to add to tree */
5701 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5702 *offset+s_octet1,(-s_octet1),buf);
5704 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5705 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5706 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5707 *offset-s_octet1,s_octet1,buf);
5711 g_free(buf); /* dont forget */
5714 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5717 * XXX - can any of these throw an exception?
5718 * If so, we need to catch the exception and free "buf".
5720 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5721 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5722 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5723 *offset-u_octet4,u_octet4,buf);
5726 g_free(buf); /* dont forget */
5736 case tk_abstract_interface:
5739 g_warning("giop: Unknown typecode data type %u \n", data_type);