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;
793 static const char *giop_ior_file = "IOR.txt";
796 * ------------------------------------------------------------------------------------------+
797 * Private helper functions
798 * ------------------------------------------------------------------------------------------+
804 * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
807 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
808 GList * newlist_start;
809 comp_req_list_entry_t * entry = NULL;
812 entry = g_malloc(sizeof(comp_req_list_entry_t));
813 opn = g_strdup(op); /* duplicate operation for storage */
816 entry->reqid = reqid;
818 entry->operation = opn;
819 entry->repoid = NULL; /* dont have yet */
821 newlist_start = g_list_append (list, entry); /* append */
823 return newlist_start;
828 * Used to find an entry with matching Frame Number FN
829 * in the complete_request_list list.
832 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
834 GList * element; /* entry in list */
835 comp_req_list_entry_t * entry_ptr = NULL;
837 element = g_list_last(giop_complete_request_list); /* start from last */
839 while(element) { /* valid list entry */
840 entry_ptr = element->data; /* grab data pointer */
841 if (entry_ptr->fn == fn) { /* similar FN */
844 element = g_list_previous(element); /* try next previous */
847 return NULL; /* no match so return NULL */
852 * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
854 * Call this when you know a FN and matching giop_sub_handle_t and repoid
856 * This is done in say, try_explicit_dissector for example.
860 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
862 comp_req_list_entry_t * entry = NULL;
863 entry = find_fn_in_list(fn); /* grab FN data entry */
867 entry->repoid = g_strdup(repoid); /* copy and store */
875 /* giop_complete_reply_hash "EQUAL" Functions */
877 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
878 const struct complete_reply_hash_key *mk1 = (const struct complete_reply_hash_key *)v;
879 const struct complete_reply_hash_key *mk2 = (const struct complete_reply_hash_key *)w;
881 if (mk1->fn == mk2->fn) {
885 return 0; /* found differences */
888 /* giop_complete_reply_hash "HASH" Functions */
890 static guint32 complete_reply_hash_fn(gconstpointer v) {
891 guint32 val; /* init hash value */
892 const struct complete_reply_hash_key *key = (const struct complete_reply_hash_key *)v;
894 val = key->fn; /* simple and unique */
901 * Insert the FN and MFN together in our complete_reply_hash.
904 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
906 struct complete_reply_hash_key key, *new_key;
907 struct complete_reply_hash_val *val = NULL;
911 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
914 return; /* FN collision */
917 new_key = se_alloc(sizeof(struct complete_reply_hash_key));
918 new_key->fn = fn; /* save FN */
920 val = se_alloc(sizeof(struct complete_reply_hash_val));
921 val->mfn = mfn; /* and MFN */
923 g_hash_table_insert(giop_complete_reply_hash, new_key, val);
928 * Find the MFN values from a given FN key.
929 * Assumes the complete_reply_hash is already populated.
932 static guint32 get_mfn_from_fn(guint32 fn) {
934 struct complete_reply_hash_key key;
935 struct complete_reply_hash_val *val = NULL;
936 guint32 mfn = fn; /* save */
939 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
942 mfn = val->mfn; /* grab it */
945 return mfn; /* mfn or fn if not found */
950 * Attempt to find the MFN for this FN, and return it.
951 * Return MFN if found, or just FN if not. This is
952 * only used when we are building
955 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
957 GList * element; /* last entry in list */
958 comp_req_list_entry_t * entry_ptr = NULL;
960 /* Need Some pretty snappy code */
962 /* Loop back from current end of complete_request_list looking for */
963 /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
966 * As this routine is only called during initial pass of data,
967 * and NOT when a user clicks, it is ok to start from Current
968 * end of complete_request_list when searching for a match.
969 * As that list is bing populated in the same order as FN's
972 * Also, can make check for same reqid more detailed, but I start
973 * with reqid. Could add say port or address checks etc later ??
977 element = g_list_last(giop_complete_request_list); /* get last */
979 while(element) { /* valid list entry */
980 entry_ptr = element->data; /* grab data pointer */
981 if (entry_ptr->reqid == reqid) { /* similar reqid */
982 return entry_ptr->fn; /* return MFN */
984 element = g_list_previous(element); /* try next previous */
987 return fn; /* no match so return FN */
991 /* Module Hash "EQUAL" Functions */
993 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
994 const struct giop_module_key *mk1 = (const struct giop_module_key *)v;
995 const struct giop_module_key *mk2 = (const struct giop_module_key *)w;
997 if (strcmp(mk1->module, mk2->module) == 0) {
1001 return 0; /* found differences */
1004 /* Module Hash "HASH" Functions */
1006 static guint32 giop_hash_module_hash(gconstpointer v) {
1009 guint32 val = 0; /* init hash value */
1011 const struct giop_module_key *key = (const struct giop_module_key *)v;
1014 * Hmm, try this simple hashing scheme for now.
1015 * ie: Simple summation, FIX later -- FS
1020 len = strlen(key->module);
1022 for (i=0; i<len; i++) {
1023 val += (guint8) key->module[i];
1032 * ------------------------------------------------------------------------------------------+
1033 * Public Utility functions
1034 * ------------------------------------------------------------------------------------------+
1041 * Routine to allow giop users to register their sub dissector function, name, and
1042 * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1043 * value returned from their proto_register_protocol(), so we can enable/disbale it
1044 * through the GUI (edit protocols).
1046 * This is used by try_explicit_giop_dissector() to find the
1047 * correct sub-dissector.
1051 void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
1053 struct giop_module_key module_key, *new_module_key;
1054 struct giop_module_val *module_val = NULL;
1056 module_key.module = module; /* module name */
1058 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1061 return; /* module name collision */
1064 /* So, passed module name should NOT exist in hash at this point.*/
1067 printf("giop:register_module: Adding Module %s to module hash \n", module);
1068 printf("giop:register_module: Module sub dissector name is %s \n", name);
1071 new_module_key = g_malloc(sizeof(struct giop_module_key));
1072 new_module_key->module = module; /* save Module or interface name from IDL */
1074 module_val = g_malloc(sizeof(struct giop_module_val));
1076 module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
1078 module_val->subh->sub_name = name; /* save dissector name */
1079 module_val->subh->sub_fn = sub; /* save subdissector*/
1080 module_val->subh->sub_proto = find_protocol_by_id(sub_proto); /* save protocol_t for subdissector's protocol */
1082 g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1089 /* Object Key Hash "EQUAL" Functions */
1091 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1092 const struct giop_object_key *v1 = (const struct giop_object_key *)v;
1093 const struct giop_object_key *v2 = (const struct giop_object_key *)w;
1095 if (v1->objkey_len != v2->objkey_len)
1096 return 0; /* no match because different length */
1098 /* Now do a byte comaprison */
1100 if (memcmp(v1->objkey,v2->objkey, v1->objkey_len) == 0) {
1101 return 1; /* compares ok */
1105 printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1108 return 0; /* found differences */
1111 /* Object Key Hash "HASH" Functions */
1113 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1114 const struct giop_object_key *key = (const struct giop_object_key *)v;
1117 guint32 val = 0; /* init hash value */
1121 * Hmm, try this simple hashing scheme for now.
1122 * ie: Simple summation
1128 printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1131 for (i=0; i< key->objkey_len; i++) {
1132 val += (guint8) key->objkey[i];
1140 * Routine to take an object key octet sequence, and length, and ptr to
1141 * a (null terminated )repository ID string, and store them in the obect key hash.
1143 * Blindly Inserts even if it does exist, See TODO at top for reason.
1146 static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
1148 struct giop_object_key objkey_key, *new_objkey_key;
1149 struct giop_object_val *objkey_val = NULL;
1151 objkey_key.objkey_len = len; /* length */
1152 objkey_key.objkey = obj; /* object key octet sequence */
1154 /* Look it up to see if it exists */
1156 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1158 /* CHANGED -- Same reqid, so abandon old entry */
1161 g_hash_table_remove(hash, &objkey_key);
1164 /* So, passed key should NOT exist in hash at this point.*/
1166 new_objkey_key = se_alloc(sizeof(struct giop_object_key));
1167 new_objkey_key->objkey_len = len; /* save it */
1168 new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */
1170 objkey_val = se_alloc(sizeof(struct giop_object_val));
1171 objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
1172 objkey_val->src = src; /* where IOR came from */
1176 printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
1177 objkey_val->repo_id, new_objkey_key->objkey_len);
1180 g_hash_table_insert(hash, new_objkey_key, objkey_val);
1187 * convert an ascii char representing a hex value,
1188 * to a numeric value.
1190 * returns value, or -1 if problem.
1194 static gint8 hex_char_to_val(guchar c){
1201 retval = c - 48; /* convert digit */
1205 c = toupper(c); /* convert to uppercase */
1206 if (c >= 'A' && c <= 'F') {
1217 * Convert from stringified IOR of the kind IOR:af4f7e459f....
1218 * to an IOR octet sequence.
1220 * User must free buffer.
1222 * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1223 * grab repoid etc for our objkey hash.
1227 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1230 gint8 tmpval; /* complete value */
1233 *out = g_new0(guint8, in_len); /* allocate buffer */
1239 /* skip past IOR: and convert character pairs to guint8 */
1241 for (i=4; i<in_len-1; i+=2) {
1242 if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1244 if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1245 g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1249 if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1250 g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1253 tmpval = tmpval_msb << 4;
1254 tmpval += tmpval_lsb;
1255 (*out)[(i-4)/2] = (guint8) tmpval;
1265 return (i-4)/2; /* length */
1272 * Simple "get a line" routine, copied from somewhere :)
1276 static int giop_getline(FILE *fp, gchar *line, int maxlen) {
1278 if (fgets(line,maxlen,fp) == NULL)
1281 return strlen(line);
1287 * Read a list of stringified IOR's from a named file, convert to IOR's
1288 * and store in object key hash
1291 static void read_IOR_strings_from_file(const gchar *name, int max_iorlen) {
1292 guchar *buf; /* NOTE reused for every line */
1294 int ior_val_len; /* length after unstringifying. */
1296 guint8 *out; /* ptr to unstringified IOR */
1297 tvbuff_t *tvb; /* temp tvbuff for dissectin IORs */
1298 guint32 my_offset = 0;
1299 gboolean stream_is_big_endian;
1302 fp = fopen(name,"r"); /* open read only */
1305 if (errno == EACCES)
1306 fprintf(stderr, "Error opening file %s for reading: %s\n", name, strerror(errno));
1310 buf = g_malloc0(max_iorlen+1); /* input buf */
1312 while ((len = giop_getline(fp,buf,max_iorlen+1)) > 0) {
1313 my_offset = 0; /* reset for every IOR read */
1315 ior_val_len = string_to_IOR(buf,len,&out); /* convert */
1319 /* Combination of tvb_new() and tvb_set_real_data().
1320 Can throw ReportedBoundsError.
1322 XXX - can it throw an exception in this case? If so, we
1323 need to catch it and clean up, but we really shouldn't allow
1324 it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
1327 tvb = tvb_new_real_data(out, ior_val_len, ior_val_len);
1329 stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1330 decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1340 fclose(fp); /* be nice */
1348 * Init routine, setup our request hash stuff, or delete old ref's
1350 * Cannot setup the module hash here as my init() may not be called before
1351 * users start registering. So I will move the module_hash stuff to
1352 * proto_register_giop, as is done with packet-rpc
1356 * Also, setup our objectkey/repoid hash here.
1360 static void giop_init(void) {
1364 * Create objkey/repoid hash, use my "equal" and "hash" functions.
1368 if (giop_objkey_hash)
1369 g_hash_table_destroy(giop_objkey_hash);
1372 * Create hash, use my "equal" and "hash" functions.
1376 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1379 * Create complete_reply_hash, use my "equal" and "hash" functions.
1383 if (giop_complete_reply_hash)
1384 g_hash_table_destroy(giop_complete_reply_hash);
1388 * Create hash, use my "equal" and "hash" functions.
1392 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1395 read_IOR_strings_from_file(giop_ior_file, 600);
1402 * Insert an entry in the GIOP Heuristic User table.
1404 * Uses giop_sub_handle_t to wrap giop user info.
1408 void register_giop_user(giop_sub_dissector_t *sub, const gchar *name, int sub_proto) {
1410 giop_sub_handle_t *subh;
1412 subh = g_malloc(sizeof (giop_sub_handle_t));
1414 subh->sub_name = name;
1416 subh->sub_proto = find_protocol_by_id(sub_proto); /* protocol_t for sub dissectors's proto_register_protocol() */
1418 giop_sub_list = g_slist_append (giop_sub_list, subh);
1424 * Lookup an object key in our object key hash, and return the corresponding
1429 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1431 struct giop_object_key objkey_key;
1432 struct giop_object_val *objkey_val = NULL;
1434 objkey_key.objkey_len = len; /* length */
1435 objkey_key.objkey = obj; /* object key octet sequence */
1437 /* Look it up to see if it exists */
1439 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1443 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1445 return objkey_val->repo_id; /* found */
1449 printf("FAILED Lookup of object key \n" );
1452 return NULL; /* not found */
1458 * Extract top level module/interface from repoid
1460 * eg from - "IDL:Echo/interface1:1.0"
1463 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1464 * get linux.org/Penguin/Teeth
1467 * User must free returned ptr after use.
1469 * TODO -- generalize for other Repoid encodings
1472 static gchar * get_modname_from_repoid(gchar *repoid) {
1474 gchar *modname = NULL;
1475 gchar *saved_repoid = NULL;
1477 guint8 stop_mod = 0; /* Index of last character of modname in Repoid */
1478 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1481 saved_repoid = g_strdup(repoid); /* make a copy */
1483 /* Must start with IDL: , otherwise I get confused */
1485 if (g_strncasecmp("IDL:",repoid,4))
1488 /* Looks like a RepoID to me, so get Module or interface name */
1490 /* TODO -- put some code here to get Module name */
1492 for(i=4; c != '\0'; i++) {
1494 stop_mod = i; /* save */
1495 if (c == ':' ) /* delimiters */
1500 /* Now create a new string based on start and stop and \0 */
1502 modname = g_strndup(repoid+4, stop_mod - start_mod);
1517 * Display a "module" hash entry
1520 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1522 struct giop_module_val *mv = (struct giop_module_val *) val;
1523 struct giop_module_key *mk = (struct giop_module_key *) key;
1525 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1532 * Display a "complete_reply " hash entry
1535 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1537 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1538 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1540 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1548 * Display an "objkey" hash entry
1551 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1553 struct giop_object_val *mv = (struct giop_object_val *) val;
1554 struct giop_object_key *mk = (struct giop_object_key *) key;
1557 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1559 for (i=0; i<mk->objkey_len; i++) {
1560 printf("%.2x ", mk->objkey[i]);
1564 * If read from file, mark it as such..
1568 printf(", Repo ID = %s \n", mv->repo_id);
1571 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1579 * Display all giop_sub_list (GSList) entries
1582 static void display_heuristic_user_list() {
1585 giop_sub_handle_t *subh; /* handle */
1587 /* Get length of list */
1588 len = g_slist_length(giop_sub_list); /* find length */
1593 for (i=0; i<len; i++) {
1594 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1595 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1601 * Display all complete_request_list (GList) entries
1604 static void display_complete_request_list() {
1607 comp_req_list_entry_t *entry;
1609 /* Get length of list */
1610 len = g_list_length(giop_complete_request_list); /* find length */
1615 for (i=0; i<len; i++) {
1616 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1617 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1618 entry->reqid,entry->operation, entry->repoid);
1626 /* Dump Hash/List contents
1628 * collection_type specifies the list or hash to dump
1632 static void giop_dump_collection(collection_data_t collection_type) {
1634 switch(collection_type) {
1635 case cd_heuristic_users:
1636 printf("+----------------------------------------------+ \n");
1637 printf("+-------------- Heuristic User (Begin) --------+ \n");
1638 printf("+----------------------------------------------+ \n");
1640 display_heuristic_user_list();
1642 printf("+----------------------------------------------+ \n");
1643 printf("+-------------- Heuristic User (End) ----------+ \n");
1644 printf("+----------------------------------------------+ \n");
1648 case cd_complete_request_list:
1649 printf("+----------------------------------------------+ \n");
1650 printf("+------------- Complete Request List (Begin) --+ \n");
1651 printf("+----------------------------------------------+ \n");
1653 display_complete_request_list();
1655 printf("+----------------------------------------------+ \n");
1656 printf("+------------ Complete Request List (End) -----+ \n");
1657 printf("+----------------------------------------------+ \n");
1661 case cd_module_hash:
1662 printf("+----------------------------------------------+ \n");
1663 printf("+-------------- Module (Begin) ----------------+ \n");
1664 printf("+----------------------------------------------+ \n");
1666 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1668 printf("+----------------------------------------------+ \n");
1669 printf("+-------------- Module ( End) -----------------+ \n");
1670 printf("+----------------------------------------------+ \n\n");
1674 case cd_objkey_hash:
1675 printf("+----------------------------------------------+ \n");
1676 printf("+-------------- Objkey (Begin) ----------------+ \n");
1677 printf("+----------------------------------------------+ \n");
1679 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1681 printf("+----------------------------------------------+ \n");
1682 printf("+-------------- Objkey (End) ------------------+ \n");
1683 printf("+----------------------------------------------+ \n\n");
1687 case cd_complete_reply_hash:
1688 printf("+----------------------------------------------+ \n");
1689 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1690 printf("+----------------------------------------------+ \n");
1692 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1694 printf("+----------------------------------------------+ \n");
1695 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1696 printf("+----------------------------------------------+ \n");
1702 printf("giop: giop_dump_collection: Unknown type \n");
1713 * Loop through all subdissectors, and call them until someone
1714 * answers (returns TRUE). This function then returns TRUE, otherwise
1717 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1720 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1721 MessageHeader *header, gchar *operation ) {
1724 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1725 giop_sub_handle_t *subh = NULL;
1726 const char *saved_proto;
1728 len = g_slist_length(giop_sub_list); /* find length */
1733 saved_proto = pinfo->current_proto;
1734 for (i=0; i<len; i++) {
1735 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1737 if (proto_is_protocol_enabled(subh->sub_proto)) {
1738 pinfo->current_proto =
1739 proto_get_protocol_short_name(subh->sub_proto);
1740 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1742 pinfo->current_proto = saved_proto;
1743 return TRUE; /* found one, lets return */
1745 } /* protocol_is_enabled */
1748 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1749 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
1751 pinfo->current_proto = saved_proto;
1752 return res; /* result */
1758 * Find the matching repoid in the module hash and call
1759 * the dissector function if offset exists.
1762 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1763 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1769 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1770 MessageHeader *header, gchar *operation, gchar *repoid ) {
1772 giop_sub_handle_t *subdiss = NULL; /* handle */
1773 gboolean res = FALSE;
1774 gchar *modname = NULL;
1775 struct giop_module_key module_key;
1776 struct giop_module_val *module_val = NULL;
1777 const char *saved_proto;
1781 * Get top level module/interface from complete repoid
1784 modname = get_modname_from_repoid(repoid);
1785 if (modname == NULL) {
1786 return res; /* unknown module name */
1790 /* Search for Module or interface name */
1792 module_key.module = modname; /* module name */
1793 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1795 if (module_val == NULL) {
1796 return res; /* module not registered */
1799 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1802 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1803 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1804 /* but only if user not clicking */
1806 if (!pinfo->fd->flags.visited)
1807 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1810 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1812 if (tvb_offset_exists(tvb, *offset)) {
1814 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1817 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1819 saved_proto = pinfo->current_proto;
1820 pinfo->current_proto =
1821 proto_get_protocol_short_name(subdiss->sub_proto);
1822 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1823 pinfo->current_proto = saved_proto;
1825 } /* protocol_is_enabled */
1826 } /* offset exists */
1829 return res; /* return result */
1834 /* Take in an array of char and create a new string.
1835 * Replace non-printable characters with periods.
1837 * The array may contain \0's so dont use strdup
1838 * The string is \0 terminated, and thus longer than
1839 * the initial sequence.
1840 * Caller must free the new string.
1843 gchar * make_printable_string (gchar *in, guint32 len) {
1845 gchar *print_string = NULL;
1847 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1848 memcpy(print_string, in, len); /* and make a copy of input data */
1850 for(i=0; i < len; i++) {
1851 if( !isprint( (unsigned char)print_string[i] ) )
1852 print_string[i] = '.';
1855 return print_string; /* return ptr */
1858 /* Determine the byte order from the GIOP MessageHeader */
1860 gboolean is_big_endian (MessageHeader * header) {
1861 gboolean big_endian = FALSE;
1863 switch (header->GIOP_version.minor) {
1866 if (header->flags & 0x01)
1886 * Calculate new offset, based on the current offset, and user supplied
1887 * "offset delta" value, and the alignment requirement.
1891 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1892 * aligned on 8 byte boundaries.
1895 static void set_new_alignment(int *offset, int delta, int alignment) {
1897 while( ( (*offset + delta) % alignment) != 0)
1906 * ------------------------------------------------------------------------------------------+
1907 * Public get_CDR_xxx functions.
1908 * ------------------------------------------------------------------------------------------+
1914 * Gets data of type any. This is encoded as a TypeCode
1915 * followed by the encoded value.
1918 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1919 gboolean stream_is_big_endian, int boundary,
1920 MessageHeader * header ) {
1922 guint32 TCKind; /* TypeCode */
1924 /* get TypeCode of any */
1925 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1927 /* dissect data of type TCKind */
1928 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1932 /* Copy a 1 octet sequence from the tvbuff
1933 * which represents a boolean value, and convert
1934 * it to a boolean value.
1935 * Offset is then incremented by 1, to indicate the 1 octet which
1936 * has been processed.
1939 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1942 val = tvb_get_guint8(tvb, *offset); /* easy */
1947 /* Copy a 1 octet sequence from the tvbuff
1948 * which represents a char, and convert
1949 * it to an char value.
1950 * offset is then incremented by 1, to indicate the 1 octet which
1951 * has been processed.
1954 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1957 val = tvb_get_guint8(tvb, *offset); /* easy */
1965 * Floating Point Data Type double IEEE 754-1985
1967 * Copy an 8 octet sequence from the tvbuff
1968 * which represents a double value, and convert
1969 * it to a double value, taking into account byte order.
1970 * offset is first incremented so that it falls on a proper alignment
1971 * boundary for double values.
1972 * offset is then incremented by 8, to indicate the 8 octets which
1973 * have been processed.
1976 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1980 /* double values must be aligned on a 8 byte boundary */
1982 while( ( (*offset + boundary) % 8) != 0)
1985 val = (stream_is_big_endian) ? tvb_get_ntohieee_double (tvb, *offset) :
1986 tvb_get_letohieee_double (tvb, *offset);
1994 /* Copy a 4 octet sequence from the tvbuff
1995 * which represents an enum value, and convert
1996 * it to an enum value, taking into account byte order.
1997 * offset is first incremented so that it falls on a proper alignment
1998 * boundary for an enum (4)
1999 * offset is then incremented by 4, to indicate the 4 octets which
2000 * have been processed.
2002 * Enum values are encoded as unsigned long.
2006 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2008 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2014 * Copy an octet sequence from the tvbuff
2015 * which represents a Fixed point decimal type, and create a string representing
2016 * a Fixed point decimal type. There are no alignment restrictions.
2017 * Size and scale of fixed decimal type is determined by IDL.
2019 * digits - IDL specified number of "digits" for this fixed type
2020 * scale - IDL specified "scale" for this fixed type
2023 * eg: typedef fixed <5,2> fixed_t;
2024 * could represent numbers like 123.45, 789.12,
2027 * As the fixed type could be any size, I will not try to fit it into our
2028 * simple types like gdouble or glong etc. I will just create a string buffer holding
2029 * a representation (after scale is applied), and with a decimal point or zero padding
2030 * inserted at the right place if necessary. The string is null terminated
2032 * so string may look like
2035 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2037 * According to spec, digits <= 31
2038 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2041 * User must remember to free the buffer
2046 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2048 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2049 guint32 i ; /* loop */
2050 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2051 /* this does not include sign, decimal point and \0 */
2052 guint32 sindex = 0; /* string index */
2053 gchar *tmpbuf; /* temp buff, holds string without scaling */
2054 guint8 tval; /* temp val storage */
2057 * how many bytes to hold digits and scale (if scale <0)
2059 * eg: fixed <5,2> = 5 digits
2060 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2064 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2068 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2070 slen = digits; /* digits */
2074 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2077 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2080 * Register a cleanup function in case on of our tvbuff accesses
2081 * throws an exception. We need to clean up tmpbuf.
2083 CLEANUP_PUSH(g_free, tmpbuf);
2085 /* If even , grab 1st dig */
2087 if (!(digits & 0x01)) {
2088 tval = get_CDR_octet(tvb,offset);
2090 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2092 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2097 * Loop, but stop BEFORE we hit last digit and sign
2098 * if digits = 1 or 2, then this part is skipped
2102 for(i=0; i< ((digits-1)/2 ); i++) {
2103 tval = get_CDR_octet(tvb,offset);
2105 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2108 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2110 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2117 printf("giop:get_CDR_fixed(): before last digit \n");
2121 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2123 tval = get_CDR_octet(tvb,offset);
2125 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2127 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2130 sign = tval & 0x0f; /* get sign */
2132 /* So now, we have all digits in an array, and the sign byte
2133 * so lets generate a printable string, taking into account the scale
2137 sindex = 0; /* reset */
2138 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2139 * \0 -- TODO check slen is reasonable first */
2141 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2146 (*seq)[sindex] = '+'; /* put sign in first string position */
2149 (*seq)[sindex] = '-';
2152 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2153 (*seq)[sindex] = '*'; /* flag as sign unkown */
2159 /* Add decimal point or padding 0's, depending if scale is positive or
2160 * negative, respectively
2164 for (i=0; i<digits-scale; i++) {
2165 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2169 (*seq)[sindex] = '.'; /* decimal point */
2172 for (i=digits-scale; i<digits; i++) {
2173 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2177 (*seq)[sindex] = '\0'; /* string terminator */
2181 /* negative scale, dump digits and pad out with 0's */
2183 for (i=0; i<digits-scale; i++) {
2185 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2187 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2192 (*seq)[sindex] = '\0'; /* string terminator */
2197 * We're done with tmpbuf, so we can call the cleanup handler to free
2198 * it, and then pop the cleanup handler.
2200 CLEANUP_CALL_AND_POP;
2203 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2213 * Floating Point Data Type float IEEE 754-1985
2215 * Copy an 4 octet sequence from the tvbuff
2216 * which represents a float value, and convert
2217 * it to a float value, taking into account byte order.
2218 * offset is first incremented so that it falls on a proper alignment
2219 * boundary for float values.
2220 * offset is then incremented by 4, to indicate the 4 octets which
2221 * have been processed.
2224 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2228 /* float values must be aligned on a 4 byte boundary */
2230 while( ( (*offset + boundary) % 4) != 0)
2233 val = (stream_is_big_endian) ? tvb_get_ntohieee_float (tvb, *offset) :
2234 tvb_get_letohieee_float (tvb, *offset);
2243 * Decode an Interface type, and display it on the tree.
2246 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2247 gboolean stream_is_big_endian, int boundary) {
2250 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2256 /* Copy a 4 octet sequence from the tvbuff
2257 * which represents a signed long value, and convert
2258 * it to an signed long vaule, taking into account byte order.
2259 * offset is first incremented so that it falls on a proper alignment
2260 * boundary for long values.
2261 * offset is then incremented by 4, to indicate the 4 octets which
2262 * have been processed.
2265 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2269 /* unsigned long values must be aligned on a 4 byte boundary */
2270 while( ( (*offset + boundary) % 4) != 0)
2273 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2274 tvb_get_letohl (tvb, *offset);
2280 /* Copy a 8 octet sequence from the tvbuff
2281 * which represents a signed long long value, and convert
2282 * it to an signed long long vaule, taking into account byte order.
2283 * offset is first incremented so that it falls on a proper alignment
2284 * boundary for long long values.
2285 * offset is then incremented by 8, to indicate the 8 octets which
2286 * have been processed.
2289 gint64 get_CDR_long_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2293 /* unsigned long long values must be aligned on a 8 byte boundary */
2294 while( ( (*offset + boundary) % 8) != 0)
2297 val = (stream_is_big_endian) ? tvb_get_ntoh64 (tvb, *offset) :
2298 tvb_get_letoh64 (tvb, *offset);
2305 * Decode an Object type, and display it on the tree.
2308 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2309 gboolean stream_is_big_endian, int boundary) {
2311 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2317 /* Copy a 1 octet sequence from the tvbuff
2318 * which represents a octet, and convert
2319 * it to an octet value.
2320 * offset is then incremented by 1, to indicate the 1 octet which
2321 * has been processed.
2324 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2327 val = tvb_get_guint8(tvb, *offset); /* easy */
2333 /* Copy a sequence of octets from the tvbuff.
2334 * Caller of this function must remember to free the
2335 * array pointed to by seq.
2336 * This function also increments offset by len.
2339 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, guint32 len) {
2342 * Make sure that the entire sequence of octets is in the buffer before
2343 * allocating the buffer, so that we don't have to worry about freeing
2344 * the buffer, and so that we don't try to allocate a buffer bigger
2345 * than the data we'll actually be copying, and thus don't run the risk
2346 * of crashing if the buffer is *so* big that we fail to allocate it
2347 * and "g_new0()" aborts.
2349 tvb_ensure_bytes_exist(tvb, *offset, len);
2352 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2353 * do what we do now, and null-terminate the string (which also means
2354 * we don't need to zero out the entire allocation, just the last byte)?
2356 *seq = g_new0(gchar, len + 1);
2357 tvb_memcpy( tvb, *seq, *offset, len);
2362 /* Copy a 2 octet sequence from the tvbuff
2363 * which represents a signed short value, and convert
2364 * it to a signed short value, taking into account byte order.
2365 * offset is first incremented so that it falls on a proper alignment
2366 * boundary for short values.
2367 * offset is then incremented by 2, to indicate the 2 octets which
2368 * have been processed.
2371 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2375 /* short values must be aligned on a 2 byte boundary */
2376 while( ( (*offset + boundary) % 2) != 0)
2379 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2380 tvb_get_letohs (tvb, *offset);
2388 /* Copy an octet sequence from the tvbuff
2389 * which represents a string, and convert
2390 * it to an string value, taking into account byte order.
2391 * offset is first incremented so that it falls on a proper alignment
2392 * boundary for string values. (begins with an unsigned long LI)
2394 * String sequence is copied to a buffer "seq". This must
2395 * be freed by the calling program.
2396 * offset is then incremented, to indicate the octets which
2397 * have been processed.
2399 * returns number of octets in the sequence
2401 * Note: This function only supports single byte encoding at the
2402 * moment until I get a handle on multibyte encoding etc.
2407 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2412 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2415 (*offset)++; /* must step past \0 delimiter */
2419 get_CDR_octet_seq(tvb, seq, offset, slength);
2421 *seq = g_strdup(""); /* zero-length string */
2424 return slength; /* return length */
2428 /* Process a sequence of octets that represent the
2429 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2431 * This function also increments offset to the correct position.
2433 * It will parse the TypeCode and output data to the "tree" provided
2436 * It returns a guint32 representing a TCKind value.
2439 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2440 gboolean stream_is_big_endian, int boundary,
2441 MessageHeader * header ) {
2444 gint16 s_octet2; /* signed int16 */
2445 guint16 u_octet2; /* unsigned int16 */
2446 guint32 u_octet4; /* unsigned int32 */
2448 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2450 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2451 *offset-sizeof(val),4,val);
2454 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2457 case tk_null: /* empty parameter list */
2459 case tk_void: /* empty parameter list */
2461 case tk_short: /* empty parameter list */
2463 case tk_long: /* empty parameter list */
2465 case tk_ushort: /* empty parameter list */
2467 case tk_ulong: /* empty parameter list */
2469 case tk_float: /* empty parameter list */
2471 case tk_double: /* empty parameter list */
2473 case tk_boolean: /* empty parameter list */
2475 case tk_char: /* empty parameter list */
2477 case tk_octet: /* empty parameter list */
2479 case tk_any: /* empty parameter list */
2481 case tk_TypeCode: /* empty parameter list */
2483 case tk_Principal: /* empty parameter list */
2485 case tk_objref: /* complex parameter list */
2486 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary);
2488 case tk_struct: /* complex parameter list */
2489 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2491 case tk_union: /* complex parameter list */
2492 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2494 case tk_enum: /* complex parameter list */
2495 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary);
2498 case tk_string: /* simple parameter list */
2499 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2501 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2502 *offset-sizeof(u_octet4),4,u_octet4);
2506 case tk_sequence: /* complex parameter list */
2507 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2509 case tk_array: /* complex parameter list */
2510 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2512 case tk_alias: /* complex parameter list */
2513 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2515 case tk_except: /* complex parameter list */
2516 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2518 case tk_longlong: /* empty parameter list */
2520 case tk_ulonglong: /* empty parameter list */
2522 case tk_longdouble: /* empty parameter list */
2524 case tk_wchar: /* empty parameter list */
2526 case tk_wstring: /* simple parameter list */
2527 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2529 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2530 *offset-sizeof(u_octet4),4,u_octet4);
2534 case tk_fixed: /* simple parameter list */
2535 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2537 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2538 *offset-sizeof(u_octet2),2,u_octet2);
2541 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2543 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2544 *offset-sizeof(s_octet2),2,s_octet2);
2548 case tk_value: /* complex parameter list */
2549 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2551 case tk_value_box: /* complex parameter list */
2552 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2554 case tk_native: /* complex parameter list */
2555 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary);
2557 case tk_abstract_interface: /* complex parameter list */
2558 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary );
2561 g_warning("giop: Unknown TCKind %u \n", val);
2570 /* Copy a 4 octet sequence from the tvbuff
2571 * which represents an unsigned long value, and convert
2572 * it to an unsigned long vaule, taking into account byte order.
2573 * offset is first incremented so that it falls on a proper alignment
2574 * boundary for unsigned long values.
2575 * offset is then incremented by 4, to indicate the 4 octets which
2576 * have been processed.
2579 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2583 /* unsigned long values must be aligned on a 4 byte boundary */
2584 while( ( (*offset + boundary) % 4) != 0)
2587 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2588 tvb_get_letohl (tvb, *offset);
2594 /* Copy a 8 octet sequence from the tvbuff
2595 * which represents an unsigned long long value, and convert
2596 * it to an unsigned long long vaule, taking into account byte order.
2597 * offset is first incremented so that it falls on a proper alignment
2598 * boundary for unsigned long long values.
2599 * offset is then incremented by 4, to indicate the 4 octets which
2600 * have been processed.
2603 guint64 get_CDR_ulong_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2607 /* unsigned long long values must be aligned on a 8 byte boundary */
2608 while( ( (*offset + boundary) % 8) != 0)
2611 val = (stream_is_big_endian) ? tvb_get_ntoh64 (tvb, *offset) :
2612 tvb_get_letoh64 (tvb, *offset);
2618 /* Copy a 2 octet sequence from the tvbuff
2619 * which represents an unsigned short value, and convert
2620 * it to an unsigned short value, taking into account byte order.
2621 * offset is first incremented so that it falls on a proper alignment
2622 * boundary for unsigned short values.
2623 * offset is then incremented by 2, to indicate the 2 octets which
2624 * have been processed.
2627 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2631 /* unsigned short values must be aligned on a 2 byte boundary */
2632 while( ( (*offset + boundary) % 2) != 0)
2635 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2636 tvb_get_letohs (tvb, *offset);
2644 /* Copy a wchar from the tvbuff.
2645 * Caller of this function must remember to free the
2646 * array pointed to by seq.
2647 * This function also increments offset according to
2650 * For GIOP 1.1 read 2 octets and return size -2. The
2651 * negation means there is no size element in the packet
2652 * and therefore no size to add to the tree.
2654 * For GIOP 1.2 read size of wchar and the size
2655 * octets. size is returned as a gint8.
2657 * For both GIOP versions the wchar is returned
2658 * as a printable string.
2662 /* NOTE: This is very primitive in that it just reads
2663 * the wchar as a series of octets and returns them
2664 * to the user. No translation is attempted based on
2665 * byte orientation, nor on code set. I.e it only
2666 * really reads past the wchar and sets the offset
2670 /* The "decoding" is done according to CORBA chapter 15.
2671 * Wchar is not supported for GIOP 1.0.
2674 gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2679 /* CORBA chapter 15:
2680 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2681 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2682 * followed by the elements of the octet sequence representing
2683 * the encoded value of the wchar.
2686 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2687 slength = 2; /* set for GIOP 1.1 length in octets */
2689 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2690 slength = get_CDR_octet(tvb,offset);
2693 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2694 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2696 /* now turn octets (wchar) into something that can be printed by the user */
2697 *seq = make_printable_string(raw_wstring, slength);
2699 g_free(raw_wstring);
2702 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2703 if (header->GIOP_version.minor < 2)
2706 return slength; /* return length */
2711 /* Copy a wstring from the tvbuff.
2712 * Caller of this function must remember to free the
2713 * array pointed to by seq.
2714 * This function also increments offset, according to
2715 * wstring length. length is returned as guint32
2718 /* NOTE: This is very primitive in that it just reads
2719 * the wstring as a series of octets and returns them
2720 * to the user. No translation is attempted based on
2721 * byte orientation, nor on code set. I.e it only
2722 * really reads past the wstring and sets the offset
2726 /* The "decoding" is done according to CORBA chapter 15.
2727 * Wstring is not supported for GIOP 1.0.
2731 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2732 int boundary, MessageHeader * header) {
2737 /* CORBA chapter 15:
2738 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2739 * length and string are NUL terminated (length???).
2740 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2744 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2746 /* get length, same for all GIOP versions,
2747 * although for 1.2 CORBA doesnt say, so assume.
2749 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2753 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2754 slength = 5; /* better than core dumping during debug */
2758 if (header->GIOP_version.minor < 2) {
2760 (*offset)++; /* must step past \0 delimiter */
2762 /* assume length is number of characters and not octets, spec not clear */
2763 slength = slength * 2; /* length in octets is 2 * wstring length */
2767 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2769 /* now turn octets (wstring) into something that can be printed by the user */
2770 *seq = make_printable_string(raw_wstring, slength);
2772 g_free(raw_wstring);
2775 return slength; /* return length */
2782 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2784 * typedef short AddressingDisposition;
2785 * const short KeyAddr = 0;
2786 * const short ProfileAddr = 1;
2787 * const short ReferenceAddr = 2;
2788 * struct IORAddressingInfo {
2789 * unsigned long selected_profile_index;
2793 * union TargetAddress switch (AddressingDisposition) {
2794 * case KeyAddr: sequence <octet> object_key;
2795 * case ProfileAddr: IOP::TaggedProfile profile;
2796 * case ReferenceAddr: IORAddressingInfo ior;
2801 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2802 gboolean stream_is_big_endian, guint32 *object_key_len,
2803 gchar **object_key_val)
2805 guint16 discriminant;
2807 gchar *p_object_key;
2812 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2815 proto_tree_add_text (tree, tvb, *offset -2, 2,
2816 "TargetAddress Discriminant: %u", discriminant);
2819 switch (discriminant)
2821 case 0: /* KeyAddr */
2822 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2825 proto_tree_add_text (tree, tvb, *offset -4, 4,
2826 "KeyAddr (object key length): %u", len);
2831 get_CDR_octet_seq(tvb, &object_key, offset, len);
2832 p_object_key = make_printable_string( object_key, len );
2836 proto_tree_add_text (tree, tvb, *offset -len, len,
2837 "KeyAddr (object key): %s", p_object_key);
2839 g_free( p_object_key );
2840 if (object_key_len) {
2841 *object_key_len = len;
2843 if (object_key_val) {
2844 *object_key_val = object_key;
2846 g_free( object_key );
2850 case 1: /* ProfileAddr */
2851 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2852 stream_is_big_endian, NULL);
2854 case 2: /* ReferenceAddr */
2855 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2859 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2860 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2863 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2871 dissect_reply_body (tvbuff_t *tvb, guint offset, packet_info *pinfo,
2872 proto_tree *tree, gboolean stream_is_big_endian,
2873 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2875 guint sequence_length;
2876 gboolean exres = FALSE; /* result of trying explicit dissectors */
2877 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2880 * comp_req_list stuff
2883 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2887 switch (reply_status)
2889 case SYSTEM_EXCEPTION:
2891 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2894 case USER_EXCEPTION:
2896 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2900 proto_tree_add_text(tree, tvb, offset-4, 4,
2901 "Exception length: %u", sequence_length);
2903 if (sequence_length != 0 && sequence_length < ITEM_LABEL_LENGTH)
2907 tvb_ensure_bytes_exist(tvb, offset, sequence_length);
2908 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2910 /* read exception id from buffer and store in*/
2912 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2916 proto_tree_add_string(tree, hf_giop_exception_id, tvb,
2917 offset, sequence_length, header->exception_id);
2923 offset += sequence_length;
2929 * Now just fall through to the NO_EXCEPTION part
2930 * as this is common .
2938 /* lookup MFN in hash directly */
2940 mfn = get_mfn_from_fn(pinfo->fd->num);
2942 if (mfn == pinfo->fd->num)
2943 return; /* no matching frame number, what am I */
2945 /* get entry for this MFN */
2946 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2949 return; /* no matching entry */
2953 * If this packet is a REPLY to a RESOLVE(request)
2955 * TODO - make this lookup faster -- FS
2958 if (!strcmp(giop_op_resolve,entry->operation)) {
2959 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2963 /* TODO -- Put stuff here for other "interesting operations" */
2967 * Call sub dissector.
2968 * First try an find a explicit sub_dissector, then if that
2969 * fails, try the heuristic method.
2974 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
2977 /* Only call heuristic if no explicit dissector was found */
2980 exres = try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
2983 if (!exres && !strcmp(giop_op_is_a, entry->operation) && tree) {
2984 proto_tree_add_text(tree, tvb, offset - 1, 1, "Type Id%s matched",
2985 get_CDR_boolean(tvb, &offset) ? "" : " not");
2989 gint stub_length = tvb_reported_length_remaining(tvb, offset);
2991 proto_tree_add_text(tree, tvb, offset, -1,
2992 "Stub data (%d byte%s)", stub_length,
2993 plurality(stub_length, "", "s"));
2998 case LOCATION_FORWARD:
2999 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3003 case LOCATION_FORWARD_PERM:
3004 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3008 case NEEDS_ADDRESSING_MODE: {
3010 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3012 proto_tree_add_text (tree, tvb, offset -2, 2,
3013 "AddressingDisposition: %u", addr_disp);
3021 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
3027 g_free(repoid); /* free resource */
3037 /* The format of the Reply Header for GIOP 1.0 and 1.1
3038 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
3040 struct ReplyHeader_1_0 {
3041 IOP::ServiceContextList service_context;
3042 unsigned long request_id;
3043 ReplyStatusType_1_0 reply_status;
3047 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3048 MessageHeader * header,
3049 gboolean stream_is_big_endian) {
3053 guint32 reply_status;
3054 proto_tree *reply_tree = NULL;
3056 guint32 mfn; /* matching frame number */
3059 tf = proto_tree_add_text (tree, tvb, offset, -1,
3060 "General Inter-ORB Protocol Reply");
3061 if (reply_tree == NULL)
3063 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3069 * Decode IOP::ServiceContextList
3072 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3074 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3076 if (check_col(pinfo->cinfo, COL_INFO)) {
3077 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3081 proto_tree_add_uint(reply_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
3084 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3086 if (check_col(pinfo->cinfo, COL_INFO)) {
3087 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3088 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3093 proto_tree_add_uint(reply_tree, hf_giop_reply_status, tvb,
3094 offset-4, 4, reply_status);
3099 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3102 if (! pinfo->fd->flags.visited) {
3103 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3104 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3105 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3109 header->req_id = request_id; /* save for sub dissector */
3110 header->rep_status = reply_status; /* save for sub dissector */
3112 /* Do we have a body */
3113 if (tvb_reported_length_remaining(tvb, offset))
3114 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3115 reply_status, header,tree);
3120 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3121 * and 1.1 header, only the fields have been rearranged. From Section
3122 * 15.4.3.1 of the CORBA 2.4 specification:
3124 * struct ReplyHeader_1_2 {
3125 * unsigned long request_id;
3126 * ReplyStatusType_1_2 reply_status;
3127 * IOP:ServiceContextList service_context;
3131 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3133 MessageHeader * header,
3134 gboolean stream_is_big_endian) {
3138 guint32 reply_status;
3139 proto_tree *reply_tree = NULL;
3141 guint32 mfn; /* matching frame number */
3144 tf = proto_tree_add_text (tree, tvb, offset, -1,
3145 "General Inter-ORB Protocol Reply");
3146 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3149 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3151 if (check_col(pinfo->cinfo, COL_INFO)) {
3152 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3156 proto_tree_add_uint (reply_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
3159 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3161 if (check_col(pinfo->cinfo, COL_INFO)) {
3162 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3163 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3168 proto_tree_add_uint(reply_tree, hf_giop_reply_status, tvb,
3169 offset-4, 4, reply_status);
3173 * Decode IOP::ServiceContextList
3176 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3179 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3182 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3185 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3188 if (! pinfo->fd->flags.visited) {
3189 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3190 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3191 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3196 * Add header to argument list so sub dissector can get header info.
3199 header->req_id = request_id; /* save for sub dissector */
3200 header->rep_status = reply_status; /* save for sub dissector */
3202 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3203 reply_status,header,tree);
3209 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3211 gboolean stream_is_big_endian) {
3215 proto_tree *cancel_request_tree = NULL;
3219 tf = proto_tree_add_text (tree, tvb, offset, -1,
3220 "General Inter-ORB Protocol CancelRequest");
3221 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3224 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3226 if (check_col(pinfo->cinfo, COL_INFO)) {
3227 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3231 proto_tree_add_uint (cancel_request_tree,hf_giop_req_id, tvb, offset-4, 4, request_id);
3237 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3238 * in section 15.4.2.1 of the CORBA 2.4 specification.
3240 * struct RequestHeader{
3241 * IOP::ServiceContextList service_context;
3242 * unsigned long request_id;
3243 * boolean response_expected;
3244 * octet reserved[3]; // Only in GIOP 1.1
3245 * sequence<octet> object_key;
3247 * CORBA::OctetSeq requesting_principal;
3251 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3253 MessageHeader * header, gboolean stream_is_big_endian)
3259 guint32 objkey_len = 0; /* object key length */
3260 gchar *objkey = NULL; /* object key sequence */
3261 gboolean exres = FALSE; /* result of trying explicit dissectors */
3264 gchar *requesting_principal;
3265 gchar *print_requesting_principal;
3266 guint8 response_expected;
3268 proto_tree *request_tree = NULL;
3271 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3276 tf = proto_tree_add_text (tree, tvb, offset, -1,
3277 "General Inter-ORB Protocol Request");
3278 if (request_tree == NULL)
3280 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3288 * Decode IOP::ServiceContextList
3291 decode_ServiceContextList(tvb, request_tree, &offset,stream_is_big_endian, 0);
3294 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3295 if (check_col(pinfo->cinfo, COL_INFO))
3297 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3301 proto_tree_add_uint (request_tree,hf_giop_req_id, tvb, offset-4, 4, request_id);
3304 response_expected = tvb_get_guint8( tvb, offset );
3306 if (check_col(pinfo->cinfo, COL_INFO))
3308 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3309 response_expected ? "two-way" : "one-way");
3313 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3314 "Response expected: %u", response_expected);
3317 if( header->GIOP_version.minor > 0)
3319 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3322 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3323 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3330 /* Length of object_key sequence */
3331 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3336 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3337 /**/ "Object Key length: %u", objkey_len);
3342 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3346 proto_tree_add_item(request_tree, hf_giop_objekt_key, tvb, offset - objkey_len, objkey_len, FALSE);
3353 * Register a cleanup function in case on of our tvbuff accesses
3354 * throws an exception. We need to clean up objkey.
3356 CLEANUP_PUSH(g_free, objkey);
3358 /* length of operation string and string */
3359 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3362 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3363 /**/ "Operation length: %u", len);
3368 if (check_col(pinfo->cinfo, COL_INFO))
3370 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3374 proto_tree_add_string (request_tree, hf_giop_req_operation,tvb, offset - len, len, operation);
3380 * Register a cleanup function in case on of our tvbuff accesses
3381 * throws an exception. We need to clean up operation.
3383 CLEANUP_PUSH(g_free, operation);
3385 /* length of requesting_principal string */
3386 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3389 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3390 /**/ "Requesting Principal Length: %u", len);
3395 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3397 print_requesting_principal = make_printable_string(requesting_principal, len);
3401 proto_tree_add_text (request_tree, tvb, offset - len, len,
3402 /**/ "Requesting Principal: %s", print_requesting_principal);
3406 g_free( print_requesting_principal );
3407 g_free( requesting_principal );
3412 * Save FN,reqid,and operation for later. Add sub_handle later.
3413 * But only if user is NOT clicking.
3416 if (! pinfo->fd->flags.visited)
3417 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3418 request_id,operation,NULL);
3422 * Call subdissector here before freeing "operation" and "key"
3423 * pass request_id also.
3424 * First try an find an explicit sub_dissector, then if that
3425 * fails, try the heuristic method.
3430 header->req_id = request_id; /* save for sub dissector */
3431 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3435 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3438 /* Only call heuristic if no explicit dissector was found */
3441 exres = try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3444 if (!exres && !strcmp(giop_op_is_a, operation) && request_tree) {
3446 len = get_CDR_string(tvb, &type_id, &offset, stream_is_big_endian, 0);
3447 proto_tree_add_text(request_tree, tvb, offset - len - 4, 4,
3448 "Type Id length: %d", len);
3449 proto_tree_add_text(request_tree, tvb, offset - len, len,
3450 "Type Id: %s", type_id);
3454 gint stub_length = tvb_reported_length_remaining(tvb, offset);
3456 proto_tree_add_text(request_tree, tvb, offset, -1,
3457 "Stub data (%d byte%s)", stub_length,
3458 plurality(stub_length, "", "s"));
3462 * We're done with operation, so we can call the cleanup handler to free
3463 * it, and then pop the cleanup handler.
3465 CLEANUP_CALL_AND_POP;
3468 * We're done with objkey, so we can call the cleanup handler to free
3469 * it, and then pop the cleanup handler.
3471 CLEANUP_CALL_AND_POP;
3475 /** The format of a GIOP 1.2 RequestHeader message is
3476 * (CORBA 2.4, sec. 15.4.2):
3478 * struct RequestHeader_1_2 {
3479 * unsigned long request_id;
3480 * octet response_flags;
3481 * octet reserved[3];
3482 * TargetAddress target;
3484 * IOP::ServiceContextList service_context;
3485 * // requesting_principal not in GIOP 1.2
3489 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3491 MessageHeader * header, gboolean stream_is_big_endian)
3496 guint8 response_flags;
3498 gchar *operation = NULL;
3499 proto_tree *request_tree = NULL;
3501 gboolean exres = FALSE; /* result of trying explicit dissectors */
3503 guint32 objkey_len = 0; /* object key length */
3504 gchar *objkey = NULL; /* object key sequence */
3505 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3509 tf = proto_tree_add_text (tree, tvb, offset, -1,
3510 "General Inter-ORB Protocol Request");
3511 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3514 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3515 if (check_col(pinfo->cinfo, COL_INFO))
3517 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3521 proto_tree_add_uint (request_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
3524 response_flags = tvb_get_guint8( tvb, offset );
3528 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3529 "Response flags: %s (%u)",
3530 val_to_str(response_flags, sync_scope, "(0x%x)"),
3534 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3537 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3538 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3542 dissect_target_address(tvb, pinfo, &offset, request_tree, stream_is_big_endian,
3543 &objkey_len, &objkey);
3545 repoid = get_repoid_from_objkey(giop_objkey_hash, objkey, objkey_len);
3549 /* length of operation string */
3550 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3553 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3554 /**/ "Operation length: %u", len);
3559 if (check_col(pinfo->cinfo, COL_INFO))
3561 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3565 proto_tree_add_string (request_tree,hf_giop_req_operation, tvb, offset - len, len, operation);
3572 * Register a cleanup function in case on of our tvbuff accesses
3573 * throws an exception. We need to clean up operation.
3575 CLEANUP_PUSH(g_free, operation);
3578 * Decode IOP::ServiceContextList
3581 decode_ServiceContextList(tvb, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3584 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3585 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3586 * GIOP octet stream start.
3589 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3592 * Save FN,reqid,and operation for later. Add sub_handle later.
3593 * But only if user is NOT clicking.
3596 if (! pinfo->fd->flags.visited)
3597 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3598 request_id,operation,NULL);
3602 * Call sub dissector.
3603 * First try an find a explicit sub_dissector, then if that
3604 * fails, try the heuristic method.
3608 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3611 /* Only call heuristic if no explicit dissector was found */
3614 exres = try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3617 if (!exres && !strcmp(giop_op_is_a, operation) && request_tree) {
3619 len = get_CDR_string(tvb, &type_id, &offset, stream_is_big_endian, 0);
3620 proto_tree_add_text(request_tree, tvb, offset - len - 4, 4,
3621 "Type Id length: %d", len);
3622 proto_tree_add_text(request_tree, tvb, offset - len, len,
3623 "Type Id: %s", type_id);
3627 gint stub_length = tvb_reported_length_remaining(tvb, offset);
3629 proto_tree_add_text(request_tree, tvb, offset, -1,
3630 "Stub data (%d byte%s)", stub_length,
3631 plurality(stub_length, "", "s"));
3635 * We're done with operation, so we can call the cleanup handler to free
3636 * it, and then pop the cleanup handler.
3638 CLEANUP_CALL_AND_POP;
3642 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3643 proto_tree * tree, MessageHeader * header,
3644 gboolean stream_is_big_endian)
3649 proto_tree *locate_request_tree = NULL;
3654 tf = proto_tree_add_text (tree, tvb, offset, -1,
3655 "General Inter-ORB Locate Request");
3656 if (locate_request_tree == NULL)
3658 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3663 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3664 if (check_col(pinfo->cinfo, COL_INFO))
3666 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3668 if (locate_request_tree)
3670 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3671 "Request id: %u", request_id);
3674 if(header->GIOP_version.minor < 2)
3676 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3677 if (locate_request_tree)
3679 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3680 "Object Key length: %u", len);
3685 if(locate_request_tree)
3688 proto_tree_add_item(locate_request_tree, hf_giop_objekt_key, tvb, offset-len, len, FALSE);
3693 else /* GIOP 1.2 and higher */
3695 dissect_target_address(tvb, pinfo, &offset, locate_request_tree,
3696 stream_is_big_endian, NULL, NULL);
3701 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3702 proto_tree * tree, MessageHeader * header,
3703 gboolean stream_is_big_endian)
3707 guint32 locate_status;
3710 proto_tree *locate_reply_tree = NULL;
3715 tf = proto_tree_add_text (tree, tvb, offset, -1,
3716 "General Inter-ORB Locate Reply");
3717 if (locate_reply_tree == NULL)
3719 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3724 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3725 if (check_col(pinfo->cinfo, COL_INFO))
3727 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3729 if (locate_reply_tree)
3731 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3732 "Request id: %u", request_id);
3735 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3736 if (locate_reply_tree)
3738 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3739 "Locate status: %s",
3740 val_to_str(locate_status, giop_locate_status_types, "(0x%x)")
3744 /* Decode the LocateReply body.
3746 * For GIOP 1.0 and 1.1 body immediately follows header.
3747 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3751 if (header->GIOP_version.minor > 1) {
3752 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3756 switch(locate_status) {
3757 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3758 case OBJECT_FORWARD_PERM:
3759 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3761 case LOC_SYSTEM_EXCEPTION:
3762 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3764 case LOC_NEEDS_ADDRESSING_MODE:
3765 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3766 if(locate_reply_tree) {
3767 proto_tree_add_text (tree, tvb, offset -2, 2,
3768 "AddressingDisposition: %u", addr_disp);
3771 default: /* others have no reply body */
3778 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3779 gboolean stream_is_big_endian)
3783 proto_tree *fragment_tree = NULL;
3788 tf = proto_tree_add_text (tree, tvb, offset, -1,
3789 "General Inter-ORB Fragment");
3790 if (fragment_tree == NULL)
3792 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3797 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3798 if (check_col(pinfo->cinfo, COL_INFO))
3800 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3804 proto_tree_add_uint (fragment_tree, hf_giop_req_id, tvb, offset-4, 4,request_id);
3810 /* Main entry point */
3812 static void dissect_giop_common (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3814 MessageHeader header;
3815 tvbuff_t *giop_header_tvb;
3816 tvbuff_t *payload_tvb;
3818 proto_tree *clnp_tree = NULL;
3821 guint minor_version;
3822 gboolean stream_is_big_endian;
3828 giop_dump_collection(cd_module_hash);
3829 giop_dump_collection(cd_objkey_hash);
3830 giop_dump_collection(cd_heuristic_users);
3831 giop_dump_collection(cd_complete_reply_hash);
3832 giop_dump_collection(cd_complete_request_list);
3835 header.exception_id = NULL;
3837 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3838 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3841 * because I have added extra elements in MessageHeader struct
3842 * for sub dissectors. -- FS
3845 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3848 if (check_col (pinfo->cinfo, COL_PROTOCOL))
3850 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3853 if (header.GIOP_version.major != GIOP_MAJOR ||
3854 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3856 /* Bad version number; should we note that and dissect the rest
3857 as data, or should this be done outside dissect_giop_common()
3858 (which is called as the PDU dissector for GIOP-over-TCP,
3859 so it can't return anything), with the test returning FALSE
3860 on the theory that it might have been some other packet that
3861 happened to begin with "GIOP"? We do the former, for now.
3862 If we should return FALSE, we should do so *without* setting
3863 the "Info" column, *without* setting the "Protocol" column,
3864 and *without* adding anything to the protocol tree. */
3866 if (check_col (pinfo->cinfo, COL_INFO))
3868 col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3869 header.GIOP_version.major, header.GIOP_version.minor);
3873 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3874 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3875 proto_tree_add_text (clnp_tree, giop_header_tvb, 0, -1,
3876 "Version %u.%u not supported",
3877 header.GIOP_version.major,
3878 header.GIOP_version.minor);
3880 call_dissector(data_handle,payload_tvb, pinfo, tree);
3884 if (check_col (pinfo->cinfo, COL_INFO))
3886 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3887 header.GIOP_version.major, header.GIOP_version.minor,
3888 val_to_str(header.message_type, giop_message_types,
3889 "Unknown message type (0x%02x)"));
3892 stream_is_big_endian = is_big_endian (&header);
3894 if (stream_is_big_endian)
3895 message_size = pntohl (&header.message_size);
3897 message_size = pletohl (&header.message_size);
3901 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3902 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3903 proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3904 "Magic number: %s", GIOP_MAGIC);
3905 proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3907 header.GIOP_version.major,
3908 header.GIOP_version.minor);
3909 switch (minor_version)
3913 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3914 "Flags: 0x%02x (%s %s)",
3916 (stream_is_big_endian) ? "big-endian" : "little-endian",
3917 (header.flags & 0x02) ? " fragment" : "");
3920 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3921 "Byte ordering: %s-endian",
3922 (stream_is_big_endian) ? "big" : "little");
3926 } /* minor_version */
3928 proto_tree_add_uint_format (clnp_tree,
3929 hf_giop_message_type,
3930 giop_header_tvb, 7, 1,
3931 header.message_type,
3932 "Message type: %s", val_to_str(header.message_type, giop_message_types, "(0x%x)"));
3934 proto_tree_add_uint (clnp_tree,
3935 hf_giop_message_size,
3936 giop_header_tvb, 8, 4, message_size);
3941 if (check_col (pinfo->cinfo, COL_INFO))
3943 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3944 header.GIOP_version.major, header.GIOP_version.minor,
3945 val_to_str(header.message_type, giop_message_types, "(0x%x)"));
3949 switch (header.message_type)
3953 if(header.GIOP_version.minor < 2)
3955 dissect_giop_request_1_1 (payload_tvb, pinfo, tree,
3956 &header, stream_is_big_endian);
3960 dissect_giop_request_1_2 (payload_tvb, pinfo, tree,
3961 &header, stream_is_big_endian);
3968 if(header.GIOP_version.minor < 2)
3970 dissect_giop_reply (payload_tvb, pinfo, tree, &header,
3971 stream_is_big_endian);
3975 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree,
3976 &header, stream_is_big_endian);
3980 dissect_giop_cancel_request(payload_tvb, pinfo, tree,
3981 stream_is_big_endian);
3984 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
3985 stream_is_big_endian);
3988 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
3989 stream_is_big_endian);
3992 dissect_giop_fragment(payload_tvb, pinfo, tree,
3993 stream_is_big_endian);
3998 } /* switch message_type */
4002 * XXX - we should catch exceptions here, so that we can free
4003 * this if an exception is thrown.
4004 * We'd then have to forward the exception.
4006 if (header.exception_id != NULL)
4007 g_free(header.exception_id);
4011 get_giop_pdu_len(tvbuff_t *tvb, int offset)
4014 MessageHeader header;
4016 gboolean stream_is_big_endian;
4018 tvb_memcpy (tvb, (guint8 *)&header, offset, GIOP_HEADER_SIZE );
4020 stream_is_big_endian = is_big_endian (&header);
4022 if (stream_is_big_endian)
4023 message_size = pntohl (&header.message_size);
4025 message_size = pletohl (&header.message_size);
4028 return message_size + GIOP_HEADER_SIZE;
4032 dissect_giop_tcp (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
4033 tcp_dissect_pdus(tvb, pinfo, tree, giop_desegment, GIOP_HEADER_SIZE,
4034 get_giop_pdu_len, dissect_giop_common);
4038 dissect_giop_heur (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
4042 conversation_t *conversation;
4043 /* check magic number and version */
4046 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
4048 tot_len = tvb_length_remaining(tvb, 0);
4050 if (tot_len < GIOP_HEADER_SIZE) /* tot_len < 12 */
4052 /* Not enough data captured to hold the GIOP header; don't try
4053 to interpret it as GIOP. */
4056 if ( tvb_memeql(tvb, 0, GIOP_MAGIC ,4) != 0)
4059 if ( pinfo->ptype == PT_TCP )
4062 * Make the GIOP dissector the dissector for this conversation.
4064 * If this isn't the first time this packet has been processed,
4065 * we've already done this work, so we don't need to do it
4068 if (!pinfo->fd->flags.visited)
4070 conversation = find_conversation(pinfo->fd->num, &pinfo->src,
4071 &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4072 if (conversation == NULL)
4074 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
4075 &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4078 conversation_set_dissector(conversation, giop_tcp_handle);
4080 dissect_giop_tcp (tvb, pinfo, tree);
4084 dissect_giop_common (tvb, pinfo, tree);
4092 proto_register_giop (void)
4094 static hf_register_info hf[] = {
4095 { &hf_giop_message_type,
4096 { "Message type", "giop.type",
4097 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4100 { &hf_giop_message_size,
4101 { "Message size", "giop.len",
4102 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4106 { "Repository ID", "giop.repoid",
4107 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4110 { &hf_giop_string_length,
4111 { "String Length", "giop.strlen",
4112 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4115 { &hf_giop_sequence_length,
4116 { "Sequence Length", "giop.seqlen",
4117 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4120 { &hf_giop_profile_id,
4121 { "Profile ID", "giop.profid",
4122 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
4127 { "IOR::type_id", "giop.typeid",
4128 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4131 { &hf_giop_iiop_v_maj,
4132 { "IIOP Major Version", "giop.iiop_vmaj",
4133 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4136 { &hf_giop_iiop_v_min,
4137 { "IIOP Minor Version", "giop.iiop_vmin",
4138 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4141 { &hf_giop_endianess,
4142 { "Endianess", "giop.endianess",
4143 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4146 { &hf_giop_IIOP_tag,
4147 { "IIOP Component TAG", "giop.iioptag",
4148 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4152 { "IOR Profile TAG", "giop.iortag",
4153 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4157 { "TypeCode enum", "giop.TCKind",
4158 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4161 { &hf_giop_typecode_count,
4162 { "TypeCode count", "giop.tccount",
4163 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4166 { &hf_giop_typecode_default_used,
4167 { "default_used", "giop.tcdefault_used",
4168 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4171 { &hf_giop_typecode_digits,
4172 { "Digits", "giop.tcdigits",
4173 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4177 { &hf_giop_typecode_length,
4178 { "Length", "giop.tclength",
4179 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4182 { &hf_giop_typecode_max_length,
4183 { "Maximum length", "giop.tcmaxlen",
4184 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4187 { &hf_giop_typecode_member_name,
4188 { "TypeCode member name", "giop.tcmemname",
4189 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4192 { &hf_giop_typecode_name,
4193 { "TypeCode name", "giop.tcname",
4194 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4197 { &hf_giop_typecode_scale,
4198 { "Scale", "giop.tcscale",
4199 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4202 { &hf_giop_typecode_ValueModifier,
4203 { "ValueModifier", "giop.tcValueModifier",
4204 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4207 { &hf_giop_typecode_Visibility,
4208 { "Visibility", "giop.tcVisibility",
4209 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4214 { &hf_giop_type_boolean,
4215 { "TypeCode boolean data", "giop.tcboolean",
4216 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4219 { &hf_giop_type_char,
4220 { "TypeCode char data", "giop.tcchar",
4221 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4224 { &hf_giop_type_double,
4225 { "TypeCode double data", "giop.tcdouble",
4226 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4229 { &hf_giop_type_enum,
4230 { "TypeCode enum data", "giop.tcenumdata",
4231 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4235 * float as double ?? -- FIX
4238 { &hf_giop_type_float,
4239 { "TypeCode float data", "giop.tcfloat",
4240 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4243 { &hf_giop_type_long,
4244 { "TypeCode long data", "giop.tclongdata",
4245 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4248 { &hf_giop_type_octet,
4249 { "TypeCode octet data", "giop.tcoctet",
4250 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4253 { &hf_giop_type_short,
4254 { "TypeCode short data", "giop.tcshortdata",
4255 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4258 { &hf_giop_type_string,
4259 { "TypeCode string data", "giop.tcstring",
4260 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4263 { &hf_giop_type_ulong,
4264 { "TypeCode ulong data", "giop.tculongdata",
4265 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4268 { &hf_giop_type_ushort,
4269 { "TypeCode ushort data", "giop.tcushortdata",
4270 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4274 * IIOP Module - Chapter 15.10.2
4277 { &hf_giop_iiop_host,
4278 { "IIOP::Profile_host", "giop.iiop.host",
4279 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4283 { &hf_giop_iiop_port,
4284 { "IIOP::Profile_port", "giop.iiop.port",
4285 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4290 * IIOP ServiceContext
4293 { &hf_giop_iop_vscid,
4294 { "VSCID", "giop.iiop.vscid",
4295 FT_UINT32, BASE_HEX, NULL, 0xffffff00, "", HFILL }
4299 { &hf_giop_iop_scid,
4300 { "SCID", "giop.iiop.scid",
4301 FT_UINT32, BASE_HEX, NULL, 0x000000ff, "", HFILL }
4306 { "Request id", "giop.request_id",
4307 FT_UINT32, BASE_DEC, NULL, 0, "", HFILL }
4310 { &hf_giop_req_operation,
4311 { "Request operation", "giop.request_op",
4312 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4314 { &hf_giop_reply_status,
4315 { "Reply status", "giop.replystatus",
4316 FT_UINT32, BASE_DEC, VALS(reply_status_types), 0x0, "", HFILL }
4318 { &hf_giop_exception_id,
4319 { "Exception id", "giop.exceptionid",
4320 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4322 { &hf_giop_objekt_key,
4323 { "Object Key", "giop.objektkey",
4324 FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
4331 static gint *ett[] = {
4335 &ett_giop_cancel_request,
4336 &ett_giop_locate_request,
4337 &ett_giop_locate_reply,
4344 module_t *giop_module;
4346 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4348 proto_register_field_array (proto_giop, hf, array_length (hf));
4349 proto_register_subtree_array (ett, array_length (ett));
4352 /* register init routine */
4354 register_init_routine( &giop_init); /* any init stuff */
4356 /* register preferences */
4357 giop_module = prefs_register_protocol(proto_giop, NULL);
4358 prefs_register_bool_preference(giop_module, "desegment_giop_messages",
4359 "Reassemble GIOP messages spanning multiple TCP segments",
4360 "Whether the GIOP dissector should reassemble messages spanning multiple TCP segments."
4361 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4363 prefs_register_string_preference(giop_module, "ior_txt", "Stringified IORs",
4364 "File containing stringified IORs, one per line.", &giop_ior_file);
4367 * Init the giop user module hash tables here, as giop users
4368 * will populate it via register_giop_user_module BEFORE my
4369 * own giop_init() is called.
4372 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4378 void proto_reg_handoff_giop (void) {
4379 data_handle = find_dissector("data");
4380 giop_tcp_handle = create_dissector_handle(dissect_giop_tcp, proto_giop);
4381 heur_dissector_add("tcp", dissect_giop_heur, proto_giop);
4382 /* Support DIOP (GIOP/UDP) */
4383 heur_dissector_add("udp", dissect_giop_heur, proto_giop);
4384 /* Port will be set by conversation */
4385 dissector_add("tcp.port", 0, giop_tcp_handle);
4394 * Ref Corba v2.4.2 Chapter 13
4402 typedef unsigned long ProfileId;
4404 const ProfileId TAG_INTERNET_IOP = 0;
4405 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4407 struct TaggedProfile {
4409 sequence <octet> profile_data;
4414 sequence <TaggedProfile> profiles;
4417 typedef unsigned long ComponentId;
4419 struct TaggedComponent {
4421 sequence <octet> component_data;
4424 typedef sequence <TaggedComponent> MultipleComponentProfile;
4430 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4431 guint32 boundary, gboolean stream_is_big_endian) {
4434 guint32 seqlen_p; /* sequence length of profiles */
4437 proto_tree *tree = NULL; /* IOR tree */
4440 gchar *repobuf; /* for repository ID */
4444 /* create a subtree */
4447 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
4448 tree = proto_item_add_subtree (tf, ett_giop_ior);
4452 /* Get type_id == Repository ID */
4454 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4457 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4458 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4460 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4461 *offset-u_octet4,u_octet4,repobuf);
4466 * Register a cleanup function in case on of our tvbuff accesses
4467 * throws an exception. We need to clean up repobuf.
4468 * We can't free it yet, as we must wait until we have the object
4469 * key, as we have to add both to the hash table.
4471 CLEANUP_PUSH(g_free, repobuf);
4473 /* Now get a sequence of profiles */
4474 /* Get sequence length (number of elements) */
4476 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4478 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4479 *offset-sizeof(seqlen_p),4,seqlen_p);
4483 /* fetch all TaggedProfiles in this sequence */
4485 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4486 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4490 * We're done with repobuf, so we can call the cleanup handler to free
4491 * it, and then pop the cleanup handler.
4493 CLEANUP_CALL_AND_POP;
4497 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4498 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4500 guint32 seqlen_pd; /* sequence length of profile data */
4502 guint32 pidtag; /* profile ID TAG */
4504 gchar *profile_data; /* profile_data pointer */
4505 gchar *p_profile_data; /* printable profile_data pointer */
4507 guint32 new_boundary; /* for encapsulations encountered */
4508 gboolean new_big_endianess; /* for encapsulations encountered */
4510 /* Get ProfileId tag */
4512 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4515 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4516 *offset-sizeof(pidtag),4,pidtag);
4519 /* get sequence length, new endianness and boundary for encapsulation */
4521 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4522 stream_is_big_endian, boundary,
4523 &new_big_endianess, &new_boundary);
4525 /* return if zero length sequence */
4532 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4533 * decode it, otherwise just dump the octet sequence
4535 * also, store IOR in our objectkey hash
4537 * TODO - handle other TAGS
4541 case IOP_TAG_INTERNET_IOP:
4543 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4548 /* fetch all octets in this sequence , but skip endianess */
4550 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4552 /* Make a printable string */
4554 p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4557 proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4558 "Profile Data: %s", p_profile_data);
4561 g_free(p_profile_data);
4563 g_free(profile_data);
4574 * Decode IIOP IOR Profile
4575 * Ref Chap 15.7.2 in Corba Spec
4579 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4580 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4581 gboolean store_flag) {
4583 guint32 i; /* loop index */
4585 guint8 v_major,v_minor; /* IIOP version */
4587 guint32 u_octet4; /* u long */
4588 guint16 u_octet2; /* u short */
4589 guint32 seqlen; /* generic sequence length */
4590 guint32 seqlen1; /* generic sequence length */
4591 gchar *objkey; /* object key pointer */
4592 gchar *p_chars; /* printable characters pointer */
4595 /* Get major/minor version */
4597 v_major = get_CDR_octet(tvb,offset);
4598 v_minor = get_CDR_octet(tvb,offset);
4602 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4603 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4604 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4605 *offset-sizeof(v_minor),1,v_minor );
4611 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4614 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4615 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4617 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4618 *offset-u_octet4,u_octet4,buf);
4622 g_free(buf); /* dont forget */
4626 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4629 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4630 *offset-sizeof(u_octet2),2,u_octet2);
4634 /* Object Key - sequence<octet> object_key */
4636 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4639 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4640 *offset-sizeof(seqlen),4,seqlen);
4644 /* fetch all octets in this sequence */
4645 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4648 * Now we may have the Repository ID from earlier, as well
4649 * as the object key sequence and lengh. So lets store them in
4650 * our objectkey hash and free buffers.
4652 * But only insert if user is not clicking and repo id not NULL.
4658 if(!pinfo->fd->flags.visited)
4659 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4664 * No pinfo, but store anyway if flag set. eg: IOR read from file
4668 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4673 proto_tree_add_item(tree, hf_giop_objekt_key, tvb, *offset -seqlen, seqlen, FALSE);
4679 * Now see if if its v1.1 or 1.2, as they can contain
4680 * extra sequence of IOP::TaggedComponents
4693 /* sequence of IOP::TaggedComponents */
4694 /* Ref Chap 13 in Corba Spec */
4696 /* get sequence length */
4697 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4700 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4701 *offset-sizeof(seqlen),4,seqlen);
4704 for (i=0; i< seqlen; i++) {
4706 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4708 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4709 *offset-sizeof(u_octet4),4,u_octet4);
4712 /* get component_data */
4713 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4715 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4716 *offset-sizeof(seqlen1),4,seqlen1);
4720 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4723 /* Make a printable string of data */
4725 p_chars = make_printable_string(buf, seqlen1);
4727 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4728 "component_data: %s", p_chars);
4742 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4749 * From Section 13.10.2.5 of the CORBA 3.0 spec.
4751 * module CONV_FRAME {
4752 * typedef unsigned long CodeSetId;
4753 * struct CodeSetContext {
4754 * CodeSetId char_data;
4755 * CodeSetId wchar_data;
4759 * Code sets are identified by a 32-bit integer id from OSF.
4760 * See: ftp://ftp.opengroup.org/pub/code_set_registry
4762 static void decode_CodeSets(tvbuff_t *tvb, proto_tree *tree, int *offset,
4763 gboolean stream_is_be, guint32 boundary) {
4765 /* The boundary being passed in is the offset where the context_data
4766 * sequence begins. */
4768 guint32 code_set_id;
4770 /* We pass in -boundary, because the alignment is calculated relative to
4771 the beginning of the context_data sequence.
4772 Inside get_CDR_ulong(), the calculation will be (offset +(- boundary)) % 4
4773 to determine the correct alignment of the short. */
4774 code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
4776 proto_tree_add_text (tree, tvb, *offset - 4, 4,
4777 "char_data: 0x%08x", code_set_id);
4779 code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
4781 proto_tree_add_text (tree, tvb, *offset - 4, 4,
4782 "wchar_data: 0x%08x", code_set_id);
4788 * From Section 2.7.3 of the Real-time CORBA 1.1 Standard, the CORBA priority
4789 * is represented in the GIOP service request as:
4792 * typedef short ServiceId;
4793 * const ServiceId RTCorbaPriority = 10;
4796 * The RT-CORBA priority is a CDR encoded short value in a sequence<octet>
4799 static void decode_RTCorbaPriority(tvbuff_t *tvb, proto_tree *tree, int *offset,
4800 gboolean stream_is_be, guint32 boundary) {
4802 /* The boundary being passed in is the offset where the context_data
4803 * sequence begins. */
4807 /* RTCorbaPriority is stored as a CDR encoded short */
4808 /* We pass in -boundary, because the alignment is calculated relative to
4809 the beginning of the context_data sequence.
4810 Inside get_CDR_short(), the calculation will be (offset + (- boundary)) % 2
4811 to determine the correct alignment of the short. */
4812 rtpriority = get_CDR_short(tvb, offset, stream_is_be, -((gint32) boundary) );
4815 /* Highlight all of context_data except for the first endian byte */
4816 proto_tree_add_text (tree, tvb, *offset - 2, 2,
4817 "RTCorbaPriority: %d", rtpriority);
4822 static void decode_UnknownServiceContext(tvbuff_t *tvb, proto_tree *tree, int *offset,
4823 gboolean stream_is_be, guint32 boundary) {
4825 guint32 context_data_len;
4826 gchar *p_context_data;
4827 gchar *context_data;
4829 /* get sequence length, and NO encapsulation */
4830 context_data_len = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4833 /* return if zero length sequence */
4834 if(context_data_len == 0)
4838 * Now decode sequence according to vendor ServiceId, but I dont
4839 * have that yet, so just dump it as data.
4842 /* fetch all octets in this sequence */
4844 get_CDR_octet_seq(tvb, &context_data, offset, context_data_len);
4846 /* Make a printable string */
4848 p_context_data = make_printable_string( context_data, context_data_len );
4851 proto_tree_add_text (tree, tvb, *offset - context_data_len , context_data_len,
4852 "context_data: %s", p_context_data);
4855 g_free(context_data);
4856 g_free(p_context_data);
4864 * typedef unsigned long ServiceID;
4866 * struct ServiceContext {
4867 * ServiceID context_id;
4868 * sequence <octet> context_data;
4870 * typedef sequence <ServiceContext> ServiceContextList;
4873 * Note: Spec says context_data is an encapsulation.
4878 void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *ptree, int *offset,
4879 gboolean stream_is_be, guint32 boundary) {
4881 guint32 seqlen; /* sequence length */
4882 guint32 context_data_len; /* context data sequence length */
4884 proto_tree *tree = NULL; /* ServiceContext tree */
4885 proto_tree *sub_tree1 = NULL;
4886 proto_item *tf = NULL, *tf_st1;
4891 guint32 vscid; /* Vendor Service context id */
4893 const gchar *service_context_name;
4894 gboolean encapsulation_is_be;
4895 guint32 encapsulation_boundary;
4896 int temp_offset, temp_offset1;
4897 int start_offset = *offset;
4899 /* create a subtree */
4902 /* set length to 0 now and correct with proto_item_set_len() later */
4903 tf = proto_tree_add_text (ptree, tvb, *offset, 0, "ServiceContextList");
4905 tree = proto_item_add_subtree (tf, ett_giop_scl);
4908 /* Get sequence length (number of elements) */
4909 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4912 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4913 *offset-sizeof(seqlen),4,seqlen);
4916 /* return if zero length sequence */
4920 if (*offset - start_offset <= 0)
4921 THROW(ReportedBoundsError);
4922 proto_item_set_len(tf, *offset - start_offset);
4928 /* Loop for all ServiceContext's */
4930 for (i=0; i<seqlen; i++) {
4932 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4933 vscid = (context_id & 0xffffff00) >> 8; /* vendor info, top 24 bits */
4934 scid = context_id & 0x000000ff; /* standard service info, lower 8 bits */
4937 proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4938 *offset-sizeof(guint32),4,vscid);
4940 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4941 *offset-sizeof(guint32),4,scid);
4945 if( vscid == 0) { /* OMG specified */
4946 service_context_name = val_to_str(scid, service_context_ids, "(0x%x)");
4947 } else { /* Proprietary vscid */
4948 service_context_name = "Unknown";
4952 proto_tree_add_text (tree, tvb, *offset -sizeof(context_id), 4,
4953 "Service Context ID: %s (%u)", service_context_name,
4957 temp_offset1 = *offset;
4958 /* The OMG has vscid of 0 reserved */
4959 if( vscid != 0 || scid > max_service_context_id ) {
4960 decode_UnknownServiceContext(tvb, tree, offset, stream_is_be, boundary);
4964 temp_offset = *offset;
4965 /* get sequence length, new endianness and boundary for encapsulation */
4966 context_data_len = get_CDR_encap_info(tvb, sub_tree1, offset,
4967 stream_is_be, boundary,
4968 &encapsulation_is_be , &encapsulation_boundary);
4971 tf_st1 = proto_tree_add_text (tree, tvb, temp_offset, sizeof(context_data_len) + context_data_len , service_context_name);
4972 sub_tree1 = proto_item_add_subtree (tf_st1, ett_giop_scl_st1);
4975 if (context_data_len == 0)
4978 /* See CORBA 3.0.2 standard, section Section 15.3.3 "Encapsulation",
4979 * for how CDR types can be marshalled into a sequence<octet>.
4980 * The first octet in the sequence determines endian order,
4981 * 0 == big-endian, 1 == little-endian
4986 case 0x01: /* Codesets */
4987 decode_CodeSets(tvb, sub_tree1, offset,
4988 encapsulation_is_be, encapsulation_boundary);
4990 case 0x0a: /* RTCorbaPriority */
4991 decode_RTCorbaPriority(tvb, sub_tree1, offset,
4992 encapsulation_is_be, encapsulation_boundary);
4996 /* Need to fill these in as we learn them */
4997 *offset = temp_offset1;
4998 decode_UnknownServiceContext(tvb, sub_tree1, offset, stream_is_be,
5002 /* Set the offset to the end of the context_data sequence */
5003 *offset = temp_offset1 + sizeof(context_data_len) + context_data_len;
5008 if (*offset - start_offset <= 0)
5009 THROW(ReportedBoundsError);
5010 proto_item_set_len(tf, *offset - start_offset);
5015 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
5018 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
5019 gboolean stream_is_big_endian,
5022 guint32 length; /* string length */
5023 guint32 minor_code_value;
5024 guint32 completion_status;
5026 gchar *buf; /* pointer to string buffer */
5028 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
5031 proto_tree_add_text(tree, tvb, *offset-4, 4,
5032 "Exception length: %u", length);
5034 proto_tree_add_text(tree, tvb, *offset - length, length,
5035 "Exception id: %s", buf );
5040 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
5041 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
5044 proto_tree_add_text(tree, tvb, *offset-8, 4,
5045 "Minor code value: %u", minor_code_value);
5046 proto_tree_add_text(tree, tvb, *offset-4, 4,
5047 "Completion Status: %u", completion_status);
5053 * Helper functions for dissecting TypeCodes
5055 * These functions decode the complex parameter lists
5056 * of TypeCodes as defined in the CORBA spec chapter 15.
5059 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5060 gboolean stream_is_big_endian, guint32 boundary) {
5062 guint32 new_boundary; /* new boundary for encapsulation */
5063 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5065 guint32 seqlen; /* sequence length */
5067 /* get sequence length, new endianness and boundary for encapsulation */
5068 seqlen = get_CDR_encap_info(tvb, tree, offset,
5069 stream_is_big_endian, boundary,
5070 &new_stream_is_big_endian, &new_boundary);
5072 /* get repository ID */
5073 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5077 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5078 hf_giop_typecode_name);
5083 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5084 gboolean stream_is_big_endian, guint32 boundary,
5085 MessageHeader * header ) {
5087 guint32 new_boundary; /* new boundary for encapsulation */
5088 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5090 guint32 count; /* parameter count (of tuples) */
5091 guint32 seqlen; /* sequence length */
5092 guint32 i; /* loop index */
5094 /* get sequence lengt,h new endianness and boundary for encapsulation */
5095 seqlen = get_CDR_encap_info(tvb, tree, offset,
5096 stream_is_big_endian, boundary,
5097 &new_stream_is_big_endian, &new_boundary);
5099 /* get repository ID */
5100 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5104 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5105 hf_giop_typecode_name);
5107 /* get count of tuples */
5108 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5110 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5111 *offset-sizeof(count),4,count);
5114 /* get all tuples */
5115 for (i=0; i< count; i++) {
5116 /* get member name */
5117 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5118 hf_giop_typecode_member_name);
5120 /* get member type */
5121 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5127 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5128 gboolean stream_is_big_endian, guint32 boundary,
5129 MessageHeader * header) {
5131 guint32 new_boundary; /* new boundary for encapsulation */
5132 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5134 guint32 TCKind; /* TypeCode */
5135 gint32 s_octet4; /* signed int32 */
5137 guint32 count; /* parameter count (of tuples) */
5138 guint32 seqlen; /* sequence length */
5139 guint32 i; /* loop index */
5141 /* get sequence legnth, new endianness and boundary for encapsulation */
5142 seqlen = get_CDR_encap_info(tvb, tree, offset,
5143 stream_is_big_endian, boundary,
5144 &new_stream_is_big_endian, &new_boundary);
5146 /* get repository ID */
5147 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5151 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5152 hf_giop_typecode_name);
5154 /* get discriminant type */
5155 TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5157 /* get default used */
5158 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
5160 proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
5161 *offset-sizeof(s_octet4),4,s_octet4);
5163 /* get count of tuples */
5164 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5166 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5167 *offset-sizeof(count),4,count);
5170 /* get all tuples */
5171 for (i=0; i< count; i++) {
5172 /* get label value, based on TCKind above */
5173 dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
5175 /* get member name */
5176 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5177 hf_giop_typecode_member_name);
5179 /* get member type */
5180 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5186 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5187 gboolean stream_is_big_endian, guint32 boundary) {
5189 guint32 new_boundary; /* new boundary for encapsulation */
5190 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5192 guint32 count; /* parameter count (of tuples) */
5193 guint32 seqlen; /* sequence length */
5194 guint32 i; /* loop index */
5196 /* get sequence length, new endianness and boundary for encapsulation */
5197 seqlen = get_CDR_encap_info(tvb, tree, offset,
5198 stream_is_big_endian, boundary,
5199 &new_stream_is_big_endian, &new_boundary);
5201 /* get repository ID */
5202 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5206 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5207 hf_giop_typecode_name);
5209 /* get count of tuples */
5210 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5212 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5213 *offset-sizeof(count),4,count);
5216 /* get all tuples */
5217 for (i=0; i< count; i++) {
5218 /* get member name */
5219 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5220 hf_giop_typecode_member_name);
5226 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5227 gboolean stream_is_big_endian, guint32 boundary,
5228 MessageHeader * header) {
5230 guint32 new_boundary; /* new boundary for encapsulation */
5231 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5233 guint32 u_octet4; /* unsigned int32 */
5235 guint32 seqlen; /* sequence length */
5237 /* get sequence length, new endianness and boundary for encapsulation */
5238 seqlen = get_CDR_encap_info(tvb, tree, offset,
5239 stream_is_big_endian, boundary,
5240 &new_stream_is_big_endian, &new_boundary);
5242 /* get element type */
5243 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5245 /* get max length */
5246 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5248 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
5249 *offset-sizeof(u_octet4),4,u_octet4);
5254 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5255 gboolean stream_is_big_endian, guint32 boundary,
5256 MessageHeader * header) {
5258 guint32 new_boundary; /* new boundary for encapsulation */
5259 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5261 guint32 u_octet4; /* unsigned int32 */
5263 guint32 seqlen; /* sequence length */
5265 /* get sequence length, new endianness and boundary for encapsulation */
5266 seqlen = get_CDR_encap_info(tvb, tree, offset,
5267 stream_is_big_endian, boundary,
5268 &new_stream_is_big_endian, &new_boundary);
5270 /* get element type */
5271 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5274 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5276 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5277 *offset-sizeof(u_octet4),4,u_octet4);
5282 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5283 gboolean stream_is_big_endian, guint32 boundary,
5284 MessageHeader * header) {
5286 guint32 new_boundary; /* new boundary for encapsulation */
5287 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5289 guint32 seqlen; /* sequence length */
5291 /* get sequence legnth, new endianness and boundary for encapsulation */
5292 seqlen = get_CDR_encap_info(tvb, tree, offset,
5293 stream_is_big_endian, boundary,
5294 &new_stream_is_big_endian, &new_boundary);
5296 /* get repository ID */
5297 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5301 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5302 hf_giop_typecode_name);
5304 /* get ??? (noname) TypeCode */
5305 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5310 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5311 gboolean stream_is_big_endian, guint32 boundary,
5312 MessageHeader * header) {
5314 guint32 new_boundary; /* new boundary for encapsulation */
5315 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5317 guint32 count; /* parameter count (of tuples) */
5318 guint32 seqlen; /* sequence length */
5319 guint32 i; /* loop index */
5321 /* get sequence length, new endianness and boundary for encapsulation */
5322 seqlen = get_CDR_encap_info(tvb, tree, offset,
5323 stream_is_big_endian, boundary,
5324 &new_stream_is_big_endian, &new_boundary);
5326 /* get repository ID */
5327 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5331 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5332 hf_giop_typecode_name);
5334 /* get count of tuples */
5335 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5337 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5338 *offset-sizeof(count),4,count);
5341 /* get all tuples */
5342 for (i=0; i< count; i++) {
5343 /* get member name */
5344 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5345 hf_giop_typecode_member_name);
5347 /* get member type */
5348 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5354 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5355 gboolean stream_is_big_endian, guint32 boundary,
5356 MessageHeader * header) {
5358 guint32 new_boundary; /* new boundary for encapsulation */
5359 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5361 gint16 s_octet2; /* signed int16 */
5363 guint32 count; /* parameter count (of tuples) */
5364 guint32 seqlen; /* sequence length */
5365 guint32 i; /* loop index */
5367 /* get sequence length, new endianness and boundary for encapsulation */
5368 seqlen = get_CDR_encap_info(tvb, tree, offset,
5369 stream_is_big_endian, boundary,
5370 &new_stream_is_big_endian, &new_boundary);
5372 /* get repository ID */
5373 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5377 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5378 hf_giop_typecode_name);
5380 /* get ValueModifier */
5381 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5383 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5384 *offset-sizeof(s_octet2),2,s_octet2);
5387 /* get conrete base */
5388 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5390 /* get count of tuples */
5391 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5393 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5394 *offset-sizeof(count),4,count);
5397 /* get all tuples */
5398 for (i=0; i< count; i++) {
5399 /* get member name */
5400 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5401 hf_giop_typecode_member_name);
5403 /* get member type */
5404 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5406 /* get Visibility */
5407 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5409 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5410 *offset-sizeof(s_octet2),2,s_octet2);
5417 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5418 gboolean stream_is_big_endian, guint32 boundary,
5419 MessageHeader * header) {
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);
5439 /* get ??? (noname) TypeCode */
5440 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5444 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5445 gboolean stream_is_big_endian, guint32 boundary) {
5447 guint32 new_boundary; /* new boundary for encapsulation */
5448 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5450 guint32 seqlen; /* sequence length */
5452 /* get sequence length, new endianness and boundary for encapsulation */
5453 seqlen = get_CDR_encap_info(tvb, tree, offset,
5454 stream_is_big_endian, boundary,
5455 &new_stream_is_big_endian, &new_boundary);
5457 /* get repository ID */
5458 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5462 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5463 hf_giop_typecode_name);
5468 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5469 gboolean stream_is_big_endian, guint32 boundary) {
5471 guint32 new_boundary; /* new boundary for encapsulation */
5472 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5474 guint32 seqlen; /* sequence length */
5476 /* get sequence length, new endianness and boundary for encapsulation */
5477 seqlen = get_CDR_encap_info(tvb, tree, offset,
5478 stream_is_big_endian, boundary,
5479 &new_stream_is_big_endian, &new_boundary);
5481 /* get repository ID */
5482 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5486 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5487 hf_giop_typecode_name);
5491 /* Typecode parameter lists are encoded as encapsulations and
5492 * this function gets the encapsulation information; see
5493 * CORBA spec chapter 15
5496 * Renamed to get_CDR_encap_info() for any encapsulation
5497 * we come across, useful helper function
5499 * Also, should return immediately if seqlen == 0.
5500 * ie: Forget about trying to grab endianess for
5501 * zero length sequence.
5503 * Caller must always check seqlen == 0, and not assume its value
5506 * Note: there seemed to be considerable confusion in corba
5507 * circles as to the correct interpretation of encapsulations,
5508 * and zero length sequences etc, but this is our best bet at the
5515 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5516 gboolean old_stream_is_big_endian, guint32 old_boundary,
5517 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5519 guint32 seqlen; /* sequence length */
5520 guint8 giop_endianess;
5522 /* Get sequence length of parameter list */
5523 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5525 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5526 *offset-sizeof(seqlen),4,seqlen);
5532 * seqlen == 0, implies no endianess and no data
5533 * so just return. Populate new_boundary_ptr and
5534 * new_stream_is_big_endian_ptr with current (old)
5535 * values, just to keep everyone happy. -- FS
5541 *new_boundary_ptr = old_boundary;
5542 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5548 /* Start of encapsulation of parameter list */
5549 *new_boundary_ptr = *offset; /* remember */
5550 giop_endianess = get_CDR_octet(tvb,offset);
5552 *new_stream_is_big_endian_ptr = ! giop_endianess;
5555 * Glib: typedef gint gboolean;
5556 * ie: It is not a guint8, so cannot use sizeof to correctly
5562 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5563 *offset-1,1,giop_endianess);
5573 * gets a TypeCode complex string parameter and
5574 * displays it in the relevant tree.
5577 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5578 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5580 guint32 u_octet4; /* unsigned int32 */
5581 gchar *buf; /* ptr to string buffer */
5584 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5587 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5588 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5590 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5594 g_free(buf); /* dont forget */
5599 * For a given data type, given by a TypeCode gets the associated data
5600 * and displays it in the relevant tree.
5603 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5604 gboolean stream_is_big_endian, guint32 boundary,
5605 MessageHeader * header, guint32 data_type ) {
5607 gboolean my_boolean; /* boolean */
5609 gint8 s_octet1; /* signed int8 */
5610 guint8 u_octet1; /* unsigned int8 */
5612 gint16 s_octet2; /* signed int16 */
5613 guint16 u_octet2; /* unsigned int16 */
5615 gint32 s_octet4; /* signed int32 */
5616 guint32 u_octet4; /* unsigned int32 */
5618 gdouble my_double; /* double */
5619 gfloat my_float; /* float */
5621 gchar *buf = NULL; /* ptr to string buffer */
5623 /* Grab the data according to data type */
5625 switch (data_type) {
5627 /* nothing to decode */
5630 /* nothing to decode */
5633 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5635 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5636 *offset-sizeof(s_octet2),2,s_octet2);
5640 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5642 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5643 *offset-sizeof(s_octet4),4,s_octet4);
5647 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5649 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5650 *offset-sizeof(u_octet2),2,u_octet2);
5654 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5656 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5657 *offset-sizeof(u_octet4),4,u_octet4);
5661 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5663 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5664 *offset-sizeof(my_float),4,my_float);
5668 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5670 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5671 *offset-sizeof(my_double),8,my_double);
5675 my_boolean = get_CDR_boolean(tvb,offset);
5677 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5678 *offset-1,1,my_boolean);
5682 u_octet1 = get_CDR_char(tvb,offset);
5684 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5685 *offset-sizeof(u_octet1),1,u_octet1);
5689 u_octet1 = get_CDR_octet(tvb,offset);
5691 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5692 *offset-sizeof(u_octet1),1,u_octet1);
5696 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5699 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5710 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5712 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5713 *offset-sizeof(u_octet4),4,u_octet4);
5717 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5719 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5720 *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);
5727 g_free(buf); /* dont forget */
5744 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5747 * XXX - can any of these throw an exception?
5748 * If so, we need to catch the exception and free "buf".
5750 if (s_octet1 < 0) { /* no size to add to tree */
5751 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5752 *offset+s_octet1,(-s_octet1),buf);
5754 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5755 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5756 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5757 *offset-s_octet1,s_octet1,buf);
5761 g_free(buf); /* dont forget */
5764 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5767 * XXX - can any of these throw an exception?
5768 * If so, we need to catch the exception and free "buf".
5770 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5771 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5772 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5773 *offset-u_octet4,u_octet4,buf);
5776 g_free(buf); /* dont forget */
5786 case tk_abstract_interface:
5789 g_warning("giop: Unknown typecode data type %u \n", data_type);