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 "packet-giop.h"
301 * Set to 1 for DEBUG output - TODO make this a runtime option
309 * ------------------------------------------------------------------------------------------+
310 * Private Helper function Declarations
311 * ------------------------------------------------------------------------------------------+
315 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
316 guint32 boundary, gboolean new_endianess, gchar *repobuf,
317 gboolean store_flag);
319 static void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *tree, int *offset,
320 gboolean stream_is_be, guint32 boundary);
322 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
323 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf);
325 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
326 guint32 boundary, gboolean stream_is_big_endian );
328 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
329 gboolean stream_is_big_endian,
332 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
333 gboolean stream_is_big_endian, guint32 boundary);
335 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
336 gboolean stream_is_big_endian, guint32 boundary,
337 MessageHeader * header);
339 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
340 gboolean stream_is_big_endian, guint32 boundary,
341 MessageHeader * header );
343 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
344 gboolean stream_is_big_endian, guint32 boundary);
346 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
347 gboolean stream_is_big_endian, guint32 boundary,
348 MessageHeader * header);
350 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
351 gboolean stream_is_big_endian, guint32 boundary,
352 MessageHeader * header);
354 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
355 gboolean stream_is_big_endian, guint32 boundary,
356 MessageHeader * header);
358 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
359 gboolean stream_is_big_endian, guint32 boundary,
360 MessageHeader * header);
362 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
363 gboolean stream_is_big_endian, guint32 boundary,
364 MessageHeader * header);
366 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
367 gboolean stream_is_big_endian, guint32 boundary,
368 MessageHeader * header);
370 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
371 gboolean stream_is_big_endian, guint32 boundary);
373 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
374 gboolean stream_is_big_endian, guint32 boundary);
377 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
378 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
380 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
381 gboolean stream_is_big_endian, guint32 boundary,
382 MessageHeader * header, guint32 data_type );
388 * ------------------------------------------------------------------------------------------+
389 * Data/Variables/Structs
390 * ------------------------------------------------------------------------------------------+
394 static int proto_giop = -1;
395 static int hf_giop_message_type = -1;
396 static int hf_giop_message_size = -1;
397 static int hf_giop_repoid = -1;
398 static int hf_giop_req_id = -1;
399 static int hf_giop_req_operation = -1;
400 static int hf_giop_string_length = -1;
401 static int hf_giop_sequence_length = -1;
402 static int hf_giop_profile_id = -1;
403 static int hf_giop_type_id = -1;
404 static int hf_giop_iiop_v_maj = -1;
405 static int hf_giop_iiop_v_min = -1;
406 static int hf_giop_endianess = -1; /* esp encapsulations */
407 static int hf_giop_IOR_tag = -1;
408 static int hf_giop_IIOP_tag = -1;
410 static int hf_giop_TCKind = -1;
411 static int hf_giop_typecode_count = -1;
412 static int hf_giop_typecode_default_used = -1;
413 static int hf_giop_typecode_digits = -1;
414 static int hf_giop_typecode_length = -1;
415 static int hf_giop_typecode_max_length = -1;
416 static int hf_giop_typecode_member_name = -1;
417 static int hf_giop_typecode_name = -1;
418 static int hf_giop_typecode_scale = -1;
419 static int hf_giop_typecode_ValueModifier = -1;
420 static int hf_giop_typecode_Visibility = -1;
422 static int hf_giop_type_boolean = -1;
423 static int hf_giop_type_char = -1;
424 static int hf_giop_type_double = -1;
425 static int hf_giop_type_enum = -1;
426 static int hf_giop_type_float = -1;
427 static int hf_giop_type_long = -1;
428 static int hf_giop_type_octet = -1;
429 static int hf_giop_type_short = -1;
430 static int hf_giop_type_string = -1;
431 static int hf_giop_type_ulong = -1;
432 static int hf_giop_type_ushort = -1;
434 static int hf_giop_iiop_host = -1;
435 static int hf_giop_iiop_port = -1;
436 static int hf_giop_iop_vscid = -1;
437 static int hf_giop_iop_scid = -1;
443 static gint ett_giop = -1;
444 static gint ett_giop_reply = -1;
445 static gint ett_giop_request = -1;
446 static gint ett_giop_cancel_request = -1;
447 static gint ett_giop_locate_request = -1;
448 static gint ett_giop_locate_reply = -1;
449 static gint ett_giop_fragment = -1;
451 static gint ett_giop_scl = -1; /* ServiceContextList */
452 static gint ett_giop_scl_st1 = -1;
453 static gint ett_giop_ior = -1; /* IOR */
455 static dissector_handle_t data_handle;
458 static const value_string giop_endianess_vals[] = {
459 { 0x0, "Big Endian" },
460 { 0x1, "Little Endian" },
464 static const value_string sync_scope[] = {
465 { 0x0, "SYNC_NONE" },
466 { 0x1, "SYNC_WITH_TRANSPORT"},
467 { 0x2, "SYNC_WITH_SERVER"},
468 { 0x3, "SYNC_WITH_TARGET"},
474 static const value_string profile_id_vals[] = {
475 { 0x0, "TAG_INTERNET_IOP" },
476 { 0x1, "TAG_MULTIPLE_COMPONENTS"},
477 { 0x2, "TAG_SCCP_IOP"},
481 static const value_string giop_message_types[] = {
484 { 0x2, "CancelRequest"},
485 { 0x3, "LocateRequest"},
486 { 0x4, "LocateReply"},
487 { 0x5, "CloseConnection"},
488 { 0x6, "MessageError"},
493 static const value_string giop_locate_status_types[] = {
494 { 0x0, "Unknown Object" },
495 { 0x1, "Object Here"},
496 { 0x2, "Object Forward"},
497 { 0x3, "Object Forward Perm"},
498 { 0x4, "Loc System Exception"},
499 { 0x5, "Loc Needs Addressing Mode"},
503 static const value_string tckind_vals[] = {
516 { 12, "tk_TypeCode"},
517 { 13, "tk_Principal"},
523 { 19, "tk_sequence"},
527 { 23, "tk_longlong"},
528 { 24, "tk_ulonglong"},
529 { 25, "tk_longdouble"},
534 { 30, "tk_value_box"},
536 { 32, "tk_abstract_interface"},
541 * These values are taken from the CORBA 3.0.2 standard,
542 * section 13.7.1 "Standard Service Contexts".
544 static const guint32 max_service_context_id = 0x10;
545 static const value_string service_context_ids[] = {
546 { 0x00, "TransactionService" },
548 { 0x02, "ChainBypassCheck"},
549 { 0x03, "ChainBypassInfo"},
550 { 0x04, "LogicalThreadId"},
551 { 0x05, "BI_DIR_IIOP"},
552 { 0x06, "SendingContextRunTime"},
553 { 0x07, "INVOCATION_POLICIES"},
554 { 0x08, "FORWARDED_IDENTITY"},
555 { 0x09, "UnknownExceptionInfo"},
556 { 0x0a, "RTCorbaPriority"},
557 { 0x0b, "RTCorbaPriorityRange"},
558 { 0x0c, "FT_GROUP_VERSION"},
559 { 0x0d, "FT_REQUEST"},
560 { 0x0e, "ExceptionDetailMessage"},
561 { 0x0f, "SecurityAttributeService"},
562 { 0x10, "ActivityService"},
569 #define GIOP_MAGIC "GIOP"
572 * TAGS for IOR Profiles
574 * Chapter 13 Corba 2.4.2
578 #define IOP_TAG_INTERNET_IOP 0
579 #define IOP_TAG_MULTIPLE_COMPONENTS 1
582 /* Max Supported versions */
584 static const guint GIOP_MAJOR = 1;
585 static const guint GIOP_MINOR = 2;
588 static const int KeyAddr = 0;
589 static const int ProfileAddr = 1;
590 static const int ReferenceAddr = 2;
594 static const value_string reply_status_types[] = {
595 { NO_EXCEPTION, "No Exception" } ,
596 { USER_EXCEPTION, "User Exception" } ,
597 { SYSTEM_EXCEPTION, "System Exception" } ,
598 { LOCATION_FORWARD, "Location Forward" } ,
599 { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
600 { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
606 typedef enum LocateStatusType
611 OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
612 LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
613 LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
617 typedef struct LocateReplyHeader
620 guint32 locate_status;
626 * DATA - complete_request_list
629 static GList *giop_complete_request_list;
631 struct comp_req_list_entry {
632 guint32 fn; /* frame number */
633 gchar * operation; /* echo echoString */
634 giop_sub_handle_t *subh; /* handle to sub dissector */
635 guint32 reqid; /* request id */
636 gchar * repoid; /* repository ID */
639 typedef struct comp_req_list_entry comp_req_list_entry_t;
643 * DATA - complete_reply_hash
645 * Maps reply FN to request MFN
648 static int complete_reply_hash_count = 1000; /* storage size for our permanent data */
649 /* ie: 1000 entries -- needs tweaking -- FS */
651 struct complete_reply_hash_key {
652 guint32 fn; /* reply frame number */
655 struct complete_reply_hash_val {
656 guint32 mfn; /* matching frame number (request) */
659 GHashTable *giop_complete_reply_hash = NULL; /* hash */
660 GMemChunk *giop_complete_reply_keys = NULL; /* key storage */
661 GMemChunk *giop_complete_reply_vals = NULL; /* val storage */
665 * DATA - Module Hash stuff to store data from register_giop_user_module
667 * ie: module (or interface ?) name, and ptr to sub_dissector handle
669 * With this knowledge, we can call a sub dissector directly,
672 * objkey -> repoid -> sub_dissector via registered module/interface
677 static int giop_module_init_count = 100; /* storage size for our permanent data */
678 /* ie: 100 entries -- needs tweaking -- FS */
680 struct giop_module_key {
681 gchar *module; /* module (interface?) name */
684 struct giop_module_val {
685 giop_sub_handle_t *subh; /* handle to sub dissector */
688 GHashTable *giop_module_hash = NULL; /* hash */
689 GMemChunk *giop_module_keys = NULL; /* key storage */
690 GMemChunk *giop_module_vals = NULL; /* val storage */
694 * DATA - GSList to store list of function (dissector) pointers.
695 * for heuristic dissection.
699 static GSList *giop_sub_list = NULL;
702 * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
703 * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
705 * With this knowledge, we can call a sub dissector directly later
708 * objkey -> repoid -> sub_dissector via registered module/interface
710 * rather than heuristic calls that do not provide operation context.
711 * (unless we pass the RepoID for a given objkey -- hmmm)
716 * Interesting operation list, add more if you want to save
720 static const char giop_op_resolve[] = "resolve";
721 static const char giop_op_bind_new_context[] = "bind_new_context";
722 static const char giop_op_bind[] = "bind";
725 * Enums for interesting local operations, that we may need to monitor
726 * with their subsequent replies
731 request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
732 request_bind_new_context_op_val, /* bind_new_context */
733 request_bind_op_val, /* bind */
734 request_get_INIT_op_val /* finding Nameserver */
740 * hash for mapping object keys onto object namespaces, so
741 * I can call the correct dissector.
747 * Where did I get the IOR from.
751 req_res = 0, /* REQUEST (resolve) */
752 file /* stringified IOR' in a file */
756 typedef enum ior_src ior_src_t;
761 * Enums for my lists and hash's
764 enum collection_data {
765 cd_heuristic_users = 0,
768 cd_complete_request_list,
769 cd_complete_reply_hash
772 typedef enum collection_data collection_data_t;
776 static int giop_objkey_init_count = 100; /* storage size for our permanent data */
777 /* ie: 100 entries -- needs tweaking -- FS */
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 */
790 GMemChunk *giop_objkey_keys = NULL; /* key storage */
791 GMemChunk *giop_objkey_vals = NULL; /* val storage */
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 = g_mem_chunk_alloc(giop_complete_reply_keys);
918 new_key->fn = fn; /* save FN */
920 val = g_mem_chunk_alloc(giop_complete_reply_vals);
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_mem_chunk_alloc(giop_module_keys);
1072 new_module_key->module = module; /* save Module or interface name from IDL */
1074 module_val = g_mem_chunk_alloc(giop_module_vals);
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 = g_mem_chunk_alloc(giop_objkey_keys);
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 = g_mem_chunk_alloc(giop_objkey_vals);
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(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 IOR.txt for reading: %s\n",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);
1370 if (giop_objkey_keys)
1371 g_mem_chunk_destroy(giop_objkey_keys);
1372 if (giop_objkey_vals)
1373 g_mem_chunk_destroy(giop_objkey_vals);
1377 * Create hash, use my "equal" and "hash" functions.
1381 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1383 giop_objkey_keys = g_mem_chunk_new("giop_objkey_keys",
1384 sizeof(struct giop_object_key),
1385 giop_objkey_init_count * sizeof(struct giop_object_key),
1388 giop_objkey_vals = g_mem_chunk_new("giop_objkey_vals",
1389 sizeof(struct giop_object_val),
1390 giop_objkey_init_count * sizeof(struct giop_object_val),
1395 * Create complete_reply_hash, use my "equal" and "hash" functions.
1399 if (giop_complete_reply_hash)
1400 g_hash_table_destroy(giop_complete_reply_hash);
1401 if (giop_complete_reply_keys)
1402 g_mem_chunk_destroy(giop_complete_reply_keys);
1403 if (giop_complete_reply_vals)
1404 g_mem_chunk_destroy(giop_complete_reply_vals);
1408 * Create hash, use my "equal" and "hash" functions.
1412 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1414 giop_complete_reply_keys = g_mem_chunk_new("giop_complete_reply_keys",
1415 sizeof(struct complete_reply_hash_key),
1416 complete_reply_hash_count * sizeof(struct complete_reply_hash_key),
1419 giop_complete_reply_vals = g_mem_chunk_new("giop_complete_reply_vals",
1420 sizeof(struct complete_reply_hash_val),
1421 complete_reply_hash_count * sizeof(struct complete_reply_hash_val),
1426 read_IOR_strings_from_file("IOR.txt", 600); /* testing */
1433 * Insert an entry in the GIOP Heuristic User table.
1435 * Uses giop_sub_handle_t to wrap giop user info.
1439 void register_giop_user(giop_sub_dissector_t *sub, gchar *name, int sub_proto) {
1441 giop_sub_handle_t *subh;
1443 subh = g_malloc(sizeof (giop_sub_handle_t));
1445 subh->sub_name = name;
1447 subh->sub_proto = find_protocol_by_id(sub_proto); /* protocol_t for sub dissectors's proto_register_protocol() */
1449 giop_sub_list = g_slist_append (giop_sub_list, subh);
1455 * Lookup an object key in our object key hash, and return the corresponding
1460 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1462 struct giop_object_key objkey_key;
1463 struct giop_object_val *objkey_val = NULL;
1465 objkey_key.objkey_len = len; /* length */
1466 objkey_key.objkey = obj; /* object key octet sequence */
1468 /* Look it up to see if it exists */
1470 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1474 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1476 return objkey_val->repo_id; /* found */
1480 printf("FAILED Lookup of object key \n" );
1483 return NULL; /* not found */
1489 * Extract top level module/interface from repoid
1491 * eg from - "IDL:Echo/interface1:1.0"
1494 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1495 * get linux.org/Penguin/Teeth
1498 * User must free returned ptr after use.
1500 * TODO -- generalize for other Repoid encodings
1503 static gchar * get_modname_from_repoid(gchar *repoid) {
1505 gchar *modname = NULL;
1506 gchar *saved_repoid = NULL;
1508 guint8 stop_mod = 0; /* Index of last character of modname in Repoid */
1509 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1512 saved_repoid = g_strdup(repoid); /* make a copy */
1514 /* Must start with IDL: , otherwise I get confused */
1516 if (g_strncasecmp("IDL:",repoid,4))
1519 /* Looks like a RepoID to me, so get Module or interface name */
1521 /* TODO -- put some code here to get Module name */
1523 for(i=4; c != '\0'; i++) {
1525 stop_mod = i; /* save */
1526 if (c == ':' ) /* delimiters */
1531 /* Now create a new string based on start and stop and \0 */
1533 modname = g_strndup(repoid+4, stop_mod - start_mod);
1548 * Display a "module" hash entry
1551 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1553 struct giop_module_val *mv = (struct giop_module_val *) val;
1554 struct giop_module_key *mk = (struct giop_module_key *) key;
1556 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1563 * Display a "complete_reply " hash entry
1566 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1568 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1569 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1571 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1579 * Display an "objkey" hash entry
1582 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1584 struct giop_object_val *mv = (struct giop_object_val *) val;
1585 struct giop_object_key *mk = (struct giop_object_key *) key;
1588 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1590 for (i=0; i<mk->objkey_len; i++) {
1591 printf("%.2x ", mk->objkey[i]);
1595 * If read from file, mark it as such..
1599 printf(", Repo ID = %s \n", mv->repo_id);
1602 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1610 * Display all giop_sub_list (GSList) entries
1613 static void display_heuristic_user_list() {
1616 giop_sub_handle_t *subh; /* handle */
1618 /* Get length of list */
1619 len = g_slist_length(giop_sub_list); /* find length */
1624 for (i=0; i<len; i++) {
1625 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1626 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1632 * Display all complete_request_list (GList) entries
1635 static void display_complete_request_list() {
1638 comp_req_list_entry_t *entry;
1640 /* Get length of list */
1641 len = g_list_length(giop_complete_request_list); /* find length */
1646 for (i=0; i<len; i++) {
1647 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1648 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1649 entry->reqid,entry->operation, entry->repoid);
1657 /* Dump Hash/List contents
1659 * collection_type specifies the list or hash to dump
1663 static void giop_dump_collection(collection_data_t collection_type) {
1665 switch(collection_type) {
1666 case cd_heuristic_users:
1667 printf("+----------------------------------------------+ \n");
1668 printf("+-------------- Heuristic User (Begin) --------+ \n");
1669 printf("+----------------------------------------------+ \n");
1671 display_heuristic_user_list();
1673 printf("+----------------------------------------------+ \n");
1674 printf("+-------------- Heuristic User (End) ----------+ \n");
1675 printf("+----------------------------------------------+ \n");
1679 case cd_complete_request_list:
1680 printf("+----------------------------------------------+ \n");
1681 printf("+------------- Complete Request List (Begin) --+ \n");
1682 printf("+----------------------------------------------+ \n");
1684 display_complete_request_list();
1686 printf("+----------------------------------------------+ \n");
1687 printf("+------------ Complete Request List (End) -----+ \n");
1688 printf("+----------------------------------------------+ \n");
1692 case cd_module_hash:
1693 printf("+----------------------------------------------+ \n");
1694 printf("+-------------- Module (Begin) ----------------+ \n");
1695 printf("+----------------------------------------------+ \n");
1697 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1699 printf("+----------------------------------------------+ \n");
1700 printf("+-------------- Module ( End) -----------------+ \n");
1701 printf("+----------------------------------------------+ \n\n");
1705 case cd_objkey_hash:
1706 printf("+----------------------------------------------+ \n");
1707 printf("+-------------- Objkey (Begin) ----------------+ \n");
1708 printf("+----------------------------------------------+ \n");
1710 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1712 printf("+----------------------------------------------+ \n");
1713 printf("+-------------- Objkey (End) ------------------+ \n");
1714 printf("+----------------------------------------------+ \n\n");
1718 case cd_complete_reply_hash:
1719 printf("+----------------------------------------------+ \n");
1720 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1721 printf("+----------------------------------------------+ \n");
1723 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1725 printf("+----------------------------------------------+ \n");
1726 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1727 printf("+----------------------------------------------+ \n");
1733 printf("giop: giop_dump_collection: Unknown type \n");
1744 * Loop through all subdissectors, and call them until someone
1745 * answers (returns TRUE). This function then returns TRUE, otherwise
1748 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1751 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1752 MessageHeader *header, gchar *operation ) {
1755 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1756 giop_sub_handle_t *subh = NULL;
1757 const char *saved_proto;
1759 len = g_slist_length(giop_sub_list); /* find length */
1764 saved_proto = pinfo->current_proto;
1765 for (i=0; i<len; i++) {
1766 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1768 if (proto_is_protocol_enabled(subh->sub_proto)) {
1769 pinfo->current_proto =
1770 proto_get_protocol_short_name(subh->sub_proto);
1771 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1773 pinfo->current_proto = saved_proto;
1774 return TRUE; /* found one, lets return */
1776 } /* protocol_is_enabled */
1779 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1780 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
1782 pinfo->current_proto = saved_proto;
1783 return res; /* result */
1789 * Find the matching repoid in the module hash and call
1790 * the dissector function if offset exists.
1793 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1794 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1800 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1801 MessageHeader *header, gchar *operation, gchar *repoid ) {
1803 giop_sub_handle_t *subdiss = NULL; /* handle */
1804 gboolean res = FALSE;
1805 gchar *modname = NULL;
1806 struct giop_module_key module_key;
1807 struct giop_module_val *module_val = NULL;
1808 const char *saved_proto;
1812 * Get top level module/interface from complete repoid
1815 modname = get_modname_from_repoid(repoid);
1816 if (modname == NULL) {
1817 return res; /* unknown module name */
1821 /* Search for Module or interface name */
1823 module_key.module = modname; /* module name */
1824 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1826 if (module_val == NULL) {
1827 return res; /* module not registered */
1830 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1833 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1834 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1835 /* but only if user not clicking */
1837 if (!pinfo->fd->flags.visited)
1838 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1841 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1843 if (tvb_offset_exists(tvb, *offset)) {
1845 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1848 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1850 saved_proto = pinfo->current_proto;
1851 pinfo->current_proto =
1852 proto_get_protocol_short_name(subdiss->sub_proto);
1853 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1854 pinfo->current_proto = saved_proto;
1856 } /* protocol_is_enabled */
1857 } /* offset exists */
1860 return res; /* return result */
1865 /* Take in an array of char and create a new string.
1866 * Replace non-printable characters with periods.
1868 * The array may contain \0's so dont use strdup
1869 * The string is \0 terminated, and thus longer than
1870 * the initial sequence.
1871 * Caller must free the new string.
1874 static gchar * make_printable_string (gchar *in, guint32 len) {
1876 gchar *print_string = NULL;
1878 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1879 memcpy(print_string, in, len); /* and make a copy of input data */
1881 for(i=0; i < len; i++) {
1882 if( !isprint( (unsigned char)print_string[i] ) )
1883 print_string[i] = '.';
1886 return print_string; /* return ptr */
1889 /* Determine the byte order from the GIOP MessageHeader */
1891 gboolean is_big_endian (MessageHeader * header) {
1892 gboolean big_endian = FALSE;
1894 switch (header->GIOP_version.minor) {
1897 if (header->flags & 0x01)
1917 * Calculate new offset, based on the current offset, and user supplied
1918 * "offset delta" value, and the alignment requirement.
1922 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1923 * aligned on 8 byte boundaries.
1926 static void set_new_alignment(int *offset, int delta, int alignment) {
1928 while( ( (*offset + delta) % alignment) != 0)
1937 * ------------------------------------------------------------------------------------------+
1938 * Public get_CDR_xxx functions.
1939 * ------------------------------------------------------------------------------------------+
1945 * Gets data of type any. This is encoded as a TypeCode
1946 * followed by the encoded value.
1949 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1950 gboolean stream_is_big_endian, int boundary,
1951 MessageHeader * header ) {
1953 guint32 TCKind; /* TypeCode */
1955 /* get TypeCode of any */
1956 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1958 /* dissect data of type TCKind */
1959 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1963 /* Copy a 1 octet sequence from the tvbuff
1964 * which represents a boolean value, and convert
1965 * it to a boolean value.
1966 * Offset is then incremented by 1, to indicate the 1 octet which
1967 * has been processed.
1970 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1973 val = tvb_get_guint8(tvb, *offset); /* easy */
1978 /* Copy a 1 octet sequence from the tvbuff
1979 * which represents a char, and convert
1980 * it to an char value.
1981 * offset is then incremented by 1, to indicate the 1 octet which
1982 * has been processed.
1985 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1988 val = tvb_get_guint8(tvb, *offset); /* easy */
1996 * Floating Point Data Type double IEEE 754-1985
1998 * Copy an 8 octet sequence from the tvbuff
1999 * which represents a double value, and convert
2000 * it to a double value, taking into account byte order.
2001 * offset is first incremented so that it falls on a proper alignment
2002 * boundary for double values.
2003 * offset is then incremented by 8, to indicate the 8 octets which
2004 * have been processed.
2007 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2011 /* double values must be aligned on a 8 byte boundary */
2013 while( ( (*offset + boundary) % 8) != 0)
2016 val = (stream_is_big_endian) ? tvb_get_ntohieee_double (tvb, *offset) :
2017 tvb_get_letohieee_double (tvb, *offset);
2025 /* Copy a 4 octet sequence from the tvbuff
2026 * which represents an enum value, and convert
2027 * it to an enum value, taking into account byte order.
2028 * offset is first incremented so that it falls on a proper alignment
2029 * boundary for an enum (4)
2030 * offset is then incremented by 4, to indicate the 4 octets which
2031 * have been processed.
2033 * Enum values are encoded as unsigned long.
2037 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2039 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2045 * Copy an octet sequence from the tvbuff
2046 * which represents a Fixed point decimal type, and create a string representing
2047 * a Fixed point decimal type. There are no alignment restrictions.
2048 * Size and scale of fixed decimal type is determined by IDL.
2050 * digits - IDL specified number of "digits" for this fixed type
2051 * scale - IDL specified "scale" for this fixed type
2054 * eg: typedef fixed <5,2> fixed_t;
2055 * could represent numbers like 123.45, 789.12,
2058 * As the fixed type could be any size, I will not try to fit it into our
2059 * simple types like gdouble or glong etc. I will just create a string buffer holding
2060 * a representation (after scale is applied), and with a decimal point or zero padding
2061 * inserted at the right place if necessary. The string is null terminated
2063 * so string may look like
2066 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2068 * According to spec, digits <= 31
2069 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2072 * User must remember to free the buffer
2077 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2079 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2080 guint32 i ; /* loop */
2081 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2082 /* this does not include sign, decimal point and \0 */
2083 guint32 sindex = 0; /* string index */
2084 gchar *tmpbuf; /* temp buff, holds string without scaling */
2085 guint8 tval; /* temp val storage */
2088 * how many bytes to hold digits and scale (if scale <0)
2090 * eg: fixed <5,2> = 5 digits
2091 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2095 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2099 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2101 slen = digits; /* digits */
2105 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2108 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2111 * Register a cleanup function in case on of our tvbuff accesses
2112 * throws an exception. We need to clean up tmpbuf.
2114 CLEANUP_PUSH(g_free, tmpbuf);
2116 /* If even , grab 1st dig */
2118 if (!(digits & 0x01)) {
2119 tval = get_CDR_octet(tvb,offset);
2121 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2123 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2128 * Loop, but stop BEFORE we hit last digit and sign
2129 * if digits = 1 or 2, then this part is skipped
2133 for(i=0; i< ((digits-1)/2 ); i++) {
2134 tval = get_CDR_octet(tvb,offset);
2136 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2139 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2141 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2148 printf("giop:get_CDR_fixed(): before last digit \n");
2152 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2154 tval = get_CDR_octet(tvb,offset);
2156 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2158 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2161 sign = tval & 0x0f; /* get sign */
2163 /* So now, we have all digits in an array, and the sign byte
2164 * so lets generate a printable string, taking into account the scale
2168 sindex = 0; /* reset */
2169 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2170 * \0 -- TODO check slen is reasonable first */
2172 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2177 (*seq)[sindex] = '+'; /* put sign in first string position */
2180 (*seq)[sindex] = '-';
2183 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2184 (*seq)[sindex] = '*'; /* flag as sign unkown */
2190 /* Add decimal point or padding 0's, depending if scale is positive or
2191 * negative, respectively
2195 for (i=0; i<digits-scale; i++) {
2196 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2200 (*seq)[sindex] = '.'; /* decimal point */
2203 for (i=digits-scale; i<digits; i++) {
2204 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2208 (*seq)[sindex] = '\0'; /* string terminator */
2212 /* negative scale, dump digits and pad out with 0's */
2214 for (i=0; i<digits-scale; i++) {
2216 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2218 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2223 (*seq)[sindex] = '\0'; /* string terminator */
2228 * We're done with tmpbuf, so we can call the cleanup handler to free
2229 * it, and then pop the cleanup handler.
2231 CLEANUP_CALL_AND_POP;
2234 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2244 * Floating Point Data Type float IEEE 754-1985
2246 * Copy an 4 octet sequence from the tvbuff
2247 * which represents a float value, and convert
2248 * it to a float value, taking into account byte order.
2249 * offset is first incremented so that it falls on a proper alignment
2250 * boundary for float values.
2251 * offset is then incremented by 4, to indicate the 4 octets which
2252 * have been processed.
2255 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2259 /* float values must be aligned on a 4 byte boundary */
2261 while( ( (*offset + boundary) % 4) != 0)
2264 val = (stream_is_big_endian) ? tvb_get_ntohieee_float (tvb, *offset) :
2265 tvb_get_letohieee_float (tvb, *offset);
2274 * Decode an Interface type, and display it on the tree.
2277 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2278 gboolean stream_is_big_endian, int boundary) {
2281 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2287 /* Copy a 4 octet sequence from the tvbuff
2288 * which represents a signed long value, and convert
2289 * it to an signed long vaule, taking into account byte order.
2290 * offset is first incremented so that it falls on a proper alignment
2291 * boundary for long values.
2292 * offset is then incremented by 4, to indicate the 4 octets which
2293 * have been processed.
2296 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2300 /* unsigned long values must be aligned on a 4 byte boundary */
2301 while( ( (*offset + boundary) % 4) != 0)
2304 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2305 tvb_get_letohl (tvb, *offset);
2312 * Decode an Object type, and display it on the tree.
2315 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2316 gboolean stream_is_big_endian, int boundary) {
2318 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2324 /* Copy a 1 octet sequence from the tvbuff
2325 * which represents a octet, and convert
2326 * it to an octet value.
2327 * offset is then incremented by 1, to indicate the 1 octet which
2328 * has been processed.
2331 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2334 val = tvb_get_guint8(tvb, *offset); /* easy */
2340 /* Copy a sequence of octets from the tvbuff.
2341 * Caller of this function must remember to free the
2342 * array pointed to by seq.
2343 * This function also increments offset by len.
2346 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, guint32 len) {
2349 * Make sure that the entire sequence of octets is in the buffer before
2350 * allocating the buffer, so that we don't have to worry about freeing
2351 * the buffer, and so that we don't try to allocate a buffer bigger
2352 * than the data we'll actually be copying, and thus don't run the risk
2353 * of crashing if the buffer is *so* big that we fail to allocate it
2354 * and "g_new0()" aborts.
2356 tvb_ensure_bytes_exist(tvb, *offset, len);
2359 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2360 * do what we do now, and null-terminate the string (which also means
2361 * we don't need to zero out the entire allocation, just the last byte)?
2363 *seq = g_new0(gchar, len + 1);
2364 tvb_memcpy( tvb, *seq, *offset, len);
2369 /* Copy a 2 octet sequence from the tvbuff
2370 * which represents a signed short value, and convert
2371 * it to a signed short value, taking into account byte order.
2372 * offset is first incremented so that it falls on a proper alignment
2373 * boundary for short values.
2374 * offset is then incremented by 2, to indicate the 2 octets which
2375 * have been processed.
2378 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2382 /* short values must be aligned on a 2 byte boundary */
2383 while( ( (*offset + boundary) % 2) != 0)
2386 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2387 tvb_get_letohs (tvb, *offset);
2395 /* Copy an octet sequence from the tvbuff
2396 * which represents a string, and convert
2397 * it to an string value, taking into account byte order.
2398 * offset is first incremented so that it falls on a proper alignment
2399 * boundary for string values. (begins with an unsigned long LI)
2401 * String sequence is copied to a buffer "seq". This must
2402 * be freed by the calling program.
2403 * offset is then incremented, to indicate the octets which
2404 * have been processed.
2406 * returns number of octets in the sequence
2408 * Note: This function only supports single byte encoding at the
2409 * moment until I get a handle on multibyte encoding etc.
2414 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2419 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2422 (*offset)++; /* must step past \0 delimiter */
2426 get_CDR_octet_seq(tvb, seq, offset, slength);
2428 *seq = g_strdup(""); /* zero-length string */
2431 return slength; /* return length */
2435 /* Process a sequence of octets that represent the
2436 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2438 * This function also increments offset to the correct position.
2440 * It will parse the TypeCode and output data to the "tree" provided
2443 * It returns a guint32 representing a TCKind value.
2446 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2447 gboolean stream_is_big_endian, int boundary,
2448 MessageHeader * header ) {
2451 gint16 s_octet2; /* signed int16 */
2452 guint16 u_octet2; /* unsigned int16 */
2453 guint32 u_octet4; /* unsigned int32 */
2455 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2457 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2458 *offset-sizeof(val),4,val);
2461 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2464 case tk_null: /* empty parameter list */
2466 case tk_void: /* empty parameter list */
2468 case tk_short: /* empty parameter list */
2470 case tk_long: /* empty parameter list */
2472 case tk_ushort: /* empty parameter list */
2474 case tk_ulong: /* empty parameter list */
2476 case tk_float: /* empty parameter list */
2478 case tk_double: /* empty parameter list */
2480 case tk_boolean: /* empty parameter list */
2482 case tk_char: /* empty parameter list */
2484 case tk_octet: /* empty parameter list */
2486 case tk_any: /* empty parameter list */
2488 case tk_TypeCode: /* empty parameter list */
2490 case tk_Principal: /* empty parameter list */
2492 case tk_objref: /* complex parameter list */
2493 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary);
2495 case tk_struct: /* complex parameter list */
2496 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2498 case tk_union: /* complex parameter list */
2499 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2501 case tk_enum: /* complex parameter list */
2502 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary);
2505 case tk_string: /* simple parameter list */
2506 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2508 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2509 *offset-sizeof(u_octet4),4,u_octet4);
2513 case tk_sequence: /* complex parameter list */
2514 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2516 case tk_array: /* complex parameter list */
2517 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2519 case tk_alias: /* complex parameter list */
2520 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2522 case tk_except: /* complex parameter list */
2523 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2525 case tk_longlong: /* empty parameter list */
2527 case tk_ulonglong: /* empty parameter list */
2529 case tk_longdouble: /* empty parameter list */
2531 case tk_wchar: /* empty parameter list */
2533 case tk_wstring: /* simple parameter list */
2534 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2536 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2537 *offset-sizeof(u_octet4),4,u_octet4);
2541 case tk_fixed: /* simple parameter list */
2542 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2544 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2545 *offset-sizeof(u_octet2),2,u_octet2);
2548 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2550 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2551 *offset-sizeof(s_octet2),2,s_octet2);
2555 case tk_value: /* complex parameter list */
2556 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2558 case tk_value_box: /* complex parameter list */
2559 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2561 case tk_native: /* complex parameter list */
2562 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary);
2564 case tk_abstract_interface: /* complex parameter list */
2565 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary );
2568 g_warning("giop: Unknown TCKind %u \n", val);
2577 /* Copy a 4 octet sequence from the tvbuff
2578 * which represents an unsigned long value, and convert
2579 * it to an unsigned long vaule, taking into account byte order.
2580 * offset is first incremented so that it falls on a proper alignment
2581 * boundary for unsigned long values.
2582 * offset is then incremented by 4, to indicate the 4 octets which
2583 * have been processed.
2586 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2590 /* unsigned long values must be aligned on a 4 byte boundary */
2591 while( ( (*offset + boundary) % 4) != 0)
2594 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2595 tvb_get_letohl (tvb, *offset);
2602 /* Copy a 2 octet sequence from the tvbuff
2603 * which represents an unsigned short value, and convert
2604 * it to an unsigned short value, taking into account byte order.
2605 * offset is first incremented so that it falls on a proper alignment
2606 * boundary for unsigned short values.
2607 * offset is then incremented by 2, to indicate the 2 octets which
2608 * have been processed.
2611 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2615 /* unsigned short values must be aligned on a 2 byte boundary */
2616 while( ( (*offset + boundary) % 2) != 0)
2619 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2620 tvb_get_letohs (tvb, *offset);
2628 /* Copy a wchar from the tvbuff.
2629 * Caller of this function must remember to free the
2630 * array pointed to by seq.
2631 * This function also increments offset according to
2634 * For GIOP 1.1 read 2 octets and return size -2. The
2635 * negation means there is no size element in the packet
2636 * and therefore no size to add to the tree.
2638 * For GIOP 1.2 read size of wchar and the size
2639 * octets. size is returned as a gint8.
2641 * For both GIOP versions the wchar is returned
2642 * as a printable string.
2646 /* NOTE: This is very primitive in that it just reads
2647 * the wchar as a series of octets and returns them
2648 * to the user. No translation is attempted based on
2649 * byte orientation, nor on code set. I.e it only
2650 * really reads past the wchar and sets the offset
2654 /* The "decoding" is done according to CORBA chapter 15.
2655 * Wchar is not supported for GIOP 1.0.
2658 gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2663 /* CORBA chapter 15:
2664 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2665 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2666 * followed by the elements of the octet sequence representing
2667 * the encoded value of the wchar.
2670 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2671 slength = 2; /* set for GIOP 1.1 length in octets */
2673 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2674 slength = get_CDR_octet(tvb,offset);
2677 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2678 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2680 /* now turn octets (wchar) into something that can be printed by the user */
2681 *seq = make_printable_string(raw_wstring, slength);
2683 g_free(raw_wstring);
2686 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2687 if (header->GIOP_version.minor < 2)
2690 return slength; /* return length */
2695 /* Copy a wstring from the tvbuff.
2696 * Caller of this function must remember to free the
2697 * array pointed to by seq.
2698 * This function also increments offset, according to
2699 * wstring length. length is returned as guint32
2702 /* NOTE: This is very primitive in that it just reads
2703 * the wstring as a series of octets and returns them
2704 * to the user. No translation is attempted based on
2705 * byte orientation, nor on code set. I.e it only
2706 * really reads past the wstring and sets the offset
2710 /* The "decoding" is done according to CORBA chapter 15.
2711 * Wstring is not supported for GIOP 1.0.
2715 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2716 int boundary, MessageHeader * header) {
2721 /* CORBA chapter 15:
2722 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2723 * length and string are NUL terminated (length???).
2724 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2728 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2730 /* get length, same for all GIOP versions,
2731 * although for 1.2 CORBA doesnt say, so assume.
2733 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2737 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2738 slength = 5; /* better than core dumping during debug */
2742 if (header->GIOP_version.minor < 2) {
2744 (*offset)++; /* must step past \0 delimiter */
2746 /* assume length is number of characters and not octets, spec not clear */
2747 slength = slength * 2; /* length in octets is 2 * wstring length */
2751 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2753 /* now turn octets (wstring) into something that can be printed by the user */
2754 *seq = make_printable_string(raw_wstring, slength);
2756 g_free(raw_wstring);
2759 return slength; /* return length */
2766 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2768 * typedef short AddressingDisposition;
2769 * const short KeyAddr = 0;
2770 * const short ProfileAddr = 1;
2771 * const short ReferenceAddr = 2;
2772 * struct IORAddressingInfo {
2773 * unsigned long selected_profile_index;
2777 * union TargetAddress switch (AddressingDisposition) {
2778 * case KeyAddr: sequence <octet> object_key;
2779 * case ProfileAddr: IOP::TaggedProfile profile;
2780 * case ReferenceAddr: IORAddressingInfo ior;
2785 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2786 gboolean stream_is_big_endian)
2788 guint16 discriminant;
2790 gchar *p_object_key;
2794 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2797 proto_tree_add_text (tree, tvb, *offset -2, 2,
2798 "TargetAddress Discriminant: %u", discriminant);
2801 switch (discriminant)
2803 case 0: /* KeyAddr */
2804 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2807 proto_tree_add_text (tree, tvb, *offset -4, 4,
2808 "KeyAddr (object key length): %u", len);
2813 get_CDR_octet_seq(tvb, &object_key, offset, len);
2814 p_object_key = make_printable_string( object_key, len );
2818 proto_tree_add_text (tree, tvb, *offset -len, len,
2819 "KeyAddr (object key): %s", p_object_key);
2821 g_free( p_object_key );
2822 g_free( object_key );
2825 case 1: /* ProfileAddr */
2826 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2827 stream_is_big_endian, NULL);
2829 case 2: /* ReferenceAddr */
2830 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2834 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2835 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2838 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2846 dissect_reply_body (tvbuff_t *tvb, guint offset, packet_info *pinfo,
2847 proto_tree *tree, gboolean stream_is_big_endian,
2848 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2850 guint sequence_length;
2851 gboolean exres = FALSE; /* result of trying explicit dissectors */
2852 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2855 * comp_req_list stuff
2858 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2862 switch (reply_status)
2864 case SYSTEM_EXCEPTION:
2866 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2869 case USER_EXCEPTION:
2871 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2875 proto_tree_add_text(tree, tvb, offset-4, 4,
2876 "Exception length: %u", sequence_length);
2878 if (sequence_length != 0)
2882 proto_tree_add_text(tree, tvb, offset, sequence_length,
2884 tvb_format_text(tvb, offset, sequence_length));
2888 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2890 /* read exception id from buffer and store in*/
2892 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2898 offset += sequence_length;
2904 * Now just fall through to the NO_EXCEPTION part
2905 * as this is common .
2913 /* lookup MFN in hash directly */
2915 mfn = get_mfn_from_fn(pinfo->fd->num);
2917 if (mfn == pinfo->fd->num)
2918 return; /* no matching frame number, what am I */
2920 /* get entry for this MFN */
2921 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2924 return; /* no matching entry */
2928 * If this packet is a REPLY to a RESOLVE(request)
2930 * TODO - make this lookup faster -- FS
2933 if (!strcmp(giop_op_resolve,entry->operation)) {
2934 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2938 /* TODO -- Put stuff here for other "interesting operations" */
2942 * Call sub dissector.
2943 * First try an find a explicit sub_dissector, then if that
2944 * fails, try the heuristic method.
2949 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
2952 /* Only call heuristic if no explicit dissector was found */
2955 exres = try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
2959 gint stub_length = tvb_reported_length_remaining(tvb, offset);
2960 proto_tree_add_text(tree, tvb, offset, -1,
2961 "Stub data (%d byte%s)", stub_length,
2962 plurality(stub_length, "", "s"));
2967 case LOCATION_FORWARD:
2968 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2972 case LOCATION_FORWARD_PERM:
2973 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2977 case NEEDS_ADDRESSING_MODE: {
2979 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2981 proto_tree_add_text (tree, tvb, offset -2, 2,
2982 "AddressingDisposition: %u", addr_disp);
2990 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
2996 g_free(repoid); /* free resource */
3006 /* The format of the Reply Header for GIOP 1.0 and 1.1
3007 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
3009 struct ReplyHeader_1_0 {
3010 IOP::ServiceContextList service_context;
3011 unsigned long request_id;
3012 ReplyStatusType_1_0 reply_status;
3016 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3017 MessageHeader * header,
3018 gboolean stream_is_big_endian) {
3022 guint32 reply_status;
3023 proto_tree *reply_tree = NULL;
3025 guint32 mfn; /* matching frame number */
3028 tf = proto_tree_add_text (tree, tvb, offset, -1,
3029 "General Inter-ORB Protocol Reply");
3030 if (reply_tree == NULL)
3032 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3038 * Decode IOP::ServiceContextList
3041 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3043 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3045 if (check_col(pinfo->cinfo, COL_INFO)) {
3046 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3050 proto_tree_add_uint(reply_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
3053 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3055 if (check_col(pinfo->cinfo, COL_INFO)) {
3056 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3057 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3062 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3064 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3069 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3072 if (! pinfo->fd->flags.visited) {
3073 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3074 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3075 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3079 header->req_id = request_id; /* save for sub dissector */
3080 header->rep_status = reply_status; /* save for sub dissector */
3082 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3083 reply_status, header,tree);
3088 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3089 * and 1.1 header, only the fields have been rearranged. From Section
3090 * 15.4.3.1 of the CORBA 2.4 specification:
3092 * struct ReplyHeader_1_2 {
3093 * unsigned long request_id;
3094 * ReplyStatusType_1_2 reply_status;
3095 * IOP:ServiceContextList service_context;
3099 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3101 MessageHeader * header,
3102 gboolean stream_is_big_endian) {
3106 guint32 reply_status;
3107 proto_tree *reply_tree = NULL;
3109 guint32 mfn; /* matching frame number */
3112 tf = proto_tree_add_text (tree, tvb, offset, -1,
3113 "General Inter-ORB Protocol Reply");
3114 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3117 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3119 if (check_col(pinfo->cinfo, COL_INFO)) {
3120 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3124 proto_tree_add_uint (reply_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
3127 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3129 if (check_col(pinfo->cinfo, COL_INFO)) {
3130 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3131 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3136 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3138 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3143 * Decode IOP::ServiceContextList
3146 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3149 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3152 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3155 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3158 if (! pinfo->fd->flags.visited) {
3159 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3160 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3161 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3166 * Add header to argument list so sub dissector can get header info.
3169 header->req_id = request_id; /* save for sub dissector */
3170 header->rep_status = reply_status; /* save for sub dissector */
3172 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3173 reply_status,header,tree);
3179 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3181 gboolean stream_is_big_endian) {
3185 proto_tree *cancel_request_tree = NULL;
3189 tf = proto_tree_add_text (tree, tvb, offset, -1,
3190 "General Inter-ORB Protocol CancelRequest");
3191 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3194 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3196 if (check_col(pinfo->cinfo, COL_INFO)) {
3197 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3201 proto_tree_add_uint (cancel_request_tree,hf_giop_req_id, tvb, offset-4, 4, request_id);
3207 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3208 * in section 15.4.2.1 of the CORBA 2.4 specification.
3210 * struct RequestHeader{
3211 * IOP::ServiceContextList service_context;
3212 * unsigned long request_id;
3213 * boolean response_expected;
3214 * octet reserved[3]; // Only in GIOP 1.1
3215 * sequence<octet> object_key;
3217 * CORBA::OctetSeq requesting_principal;
3221 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3223 MessageHeader * header, gboolean stream_is_big_endian)
3229 guint32 objkey_len = 0; /* object key length */
3230 gchar *objkey = NULL; /* object key sequence */
3231 gchar *print_objkey; /* printable object key sequence */
3232 gboolean exres = FALSE; /* result of trying explicit dissectors */
3235 gchar *requesting_principal;
3236 gchar *print_requesting_principal;
3237 guint8 response_expected;
3239 proto_tree *request_tree = NULL;
3242 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3247 tf = proto_tree_add_text (tree, tvb, offset, -1,
3248 "General Inter-ORB Protocol Request");
3249 if (request_tree == NULL)
3251 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3259 * Decode IOP::ServiceContextList
3262 decode_ServiceContextList(tvb, request_tree, &offset,stream_is_big_endian, 0);
3265 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3266 if (check_col(pinfo->cinfo, COL_INFO))
3268 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3272 proto_tree_add_uint (request_tree,hf_giop_req_id, tvb, offset-4, 4, request_id);
3275 response_expected = tvb_get_guint8( tvb, offset );
3277 if (check_col(pinfo->cinfo, COL_INFO))
3279 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3280 response_expected ? "two-way" : "one-way");
3284 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3285 "Response expected: %u", response_expected);
3288 if( header->GIOP_version.minor > 0)
3290 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3293 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3294 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3301 /* Length of object_key sequence */
3302 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3307 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3308 /**/ "Object Key length: %u", objkey_len);
3313 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3315 print_objkey = make_printable_string(objkey, objkey_len);
3319 proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
3320 /**/ "Object Key: %s", print_objkey);
3324 g_free( print_objkey );
3328 * Register a cleanup function in case on of our tvbuff accesses
3329 * throws an exception. We need to clean up objkey.
3331 CLEANUP_PUSH(g_free, objkey);
3333 /* length of operation string and string */
3334 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3337 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3338 /**/ "Operation length: %u", len);
3343 if (check_col(pinfo->cinfo, COL_INFO))
3345 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3349 proto_tree_add_string (request_tree, hf_giop_req_operation,tvb, offset - len, len, operation);
3355 * Register a cleanup function in case on of our tvbuff accesses
3356 * throws an exception. We need to clean up operation.
3358 CLEANUP_PUSH(g_free, operation);
3360 /* length of requesting_principal string */
3361 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3364 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3365 /**/ "Requesting Principal Length: %u", len);
3370 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3372 print_requesting_principal = make_printable_string(requesting_principal, len);
3376 proto_tree_add_text (request_tree, tvb, offset - len, len,
3377 /**/ "Requesting Principal: %s", print_requesting_principal);
3381 g_free( print_requesting_principal );
3382 g_free( requesting_principal );
3387 * Save FN,reqid,and operation for later. Add sub_handle later.
3388 * But only if user is NOT clicking.
3391 if (! pinfo->fd->flags.visited)
3392 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3393 request_id,operation,NULL);
3397 * Call subdissector here before freeing "operation" and "key"
3398 * pass request_id also.
3399 * First try an find an explicit sub_dissector, then if that
3400 * fails, try the heuristic method.
3405 header->req_id = request_id; /* save for sub dissector */
3406 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3410 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3413 /* Only call heuristic if no explicit dissector was found */
3416 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3420 gint stub_length = tvb_reported_length_remaining(tvb, offset);
3421 proto_tree_add_text(request_tree, tvb, offset, -1,
3422 "Stub data (%d byte%s)", stub_length,
3423 plurality(stub_length, "", "s"));
3427 * We're done with operation, so we can call the cleanup handler to free
3428 * it, and then pop the cleanup handler.
3430 CLEANUP_CALL_AND_POP;
3433 * We're done with objkey, so we can call the cleanup handler to free
3434 * it, and then pop the cleanup handler.
3436 CLEANUP_CALL_AND_POP;
3440 /** The format of a GIOP 1.2 RequestHeader message is
3441 * (CORBA 2.4, sec. 15.4.2):
3443 * struct RequestHeader_1_2 {
3444 * unsigned long request_id;
3445 * octet response_flags;
3446 * octet reserved[3];
3447 * TargetAddress target;
3449 * IOP::ServiceContextList service_context;
3450 * // requesting_principal not in GIOP 1.2
3454 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3456 MessageHeader * header, gboolean stream_is_big_endian)
3461 guint8 response_flags;
3463 gchar *operation = NULL;
3464 proto_tree *request_tree = NULL;
3466 gboolean exres = FALSE; /* result of trying explicit dissectors */
3468 gchar *repoid = NULL;
3473 tf = proto_tree_add_text (tree, tvb, offset, -1,
3474 "General Inter-ORB Protocol Request");
3475 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3478 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3479 if (check_col(pinfo->cinfo, COL_INFO))
3481 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3485 proto_tree_add_uint (request_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
3488 response_flags = tvb_get_guint8( tvb, offset );
3492 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3493 "Response flags: %s (%u)",
3494 match_strval(response_flags, sync_scope),
3498 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3501 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3502 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3506 dissect_target_address(tvb, pinfo, &offset, request_tree, stream_is_big_endian);
3508 /* length of operation string */
3509 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3512 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3513 /**/ "Operation length: %u", len);
3518 if (check_col(pinfo->cinfo, COL_INFO))
3520 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3524 proto_tree_add_string (request_tree,hf_giop_req_operation, tvb, offset - len, len, operation);
3531 * Register a cleanup function in case on of our tvbuff accesses
3532 * throws an exception. We need to clean up operation.
3534 CLEANUP_PUSH(g_free, operation);
3537 * Decode IOP::ServiceContextList
3540 decode_ServiceContextList(tvb, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3543 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3544 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3545 * GIOP octet stream start.
3548 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3551 * Save FN,reqid,and operation for later. Add sub_handle later.
3552 * But only if user is NOT clicking.
3555 if (! pinfo->fd->flags.visited)
3556 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3557 request_id,operation,NULL);
3561 * Call sub dissector.
3562 * First try an find a explicit sub_dissector, then if that
3563 * fails, try the heuristic method.
3568 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3571 /* Only call heuristic if no explicit dissector was found */
3574 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3578 gint stub_length = tvb_reported_length_remaining(tvb, offset);
3579 proto_tree_add_text(request_tree, tvb, offset, -1,
3580 "Stub data (%d byte%s)", stub_length,
3581 plurality(stub_length, "", "s"));
3585 * We're done with operation, so we can call the cleanup handler to free
3586 * it, and then pop the cleanup handler.
3588 CLEANUP_CALL_AND_POP;
3592 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3593 proto_tree * tree, MessageHeader * header,
3594 gboolean stream_is_big_endian)
3600 gchar *p_object_key;
3601 proto_tree *locate_request_tree = NULL;
3606 tf = proto_tree_add_text (tree, tvb, offset, -1,
3607 "General Inter-ORB Locate Request");
3608 if (locate_request_tree == NULL)
3610 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3615 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3616 if (check_col(pinfo->cinfo, COL_INFO))
3618 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3620 if (locate_request_tree)
3622 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3623 "Request id: %u", request_id);
3626 if(header->GIOP_version.minor < 2)
3628 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3629 if (locate_request_tree)
3631 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3632 "Object Key length: %u", len);
3636 get_CDR_octet_seq(tvb, &object_key, &offset, len);
3638 p_object_key = make_printable_string(object_key, len);
3640 if(locate_request_tree)
3643 proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
3644 "Object Key: %s", p_object_key);
3647 g_free(p_object_key);
3651 else /* GIOP 1.2 and higher */
3653 dissect_target_address(tvb, pinfo, &offset, locate_request_tree,
3654 stream_is_big_endian);
3660 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3661 proto_tree * tree, MessageHeader * header,
3662 gboolean stream_is_big_endian)
3666 guint32 locate_status;
3669 proto_tree *locate_reply_tree = NULL;
3674 tf = proto_tree_add_text (tree, tvb, offset, -1,
3675 "General Inter-ORB Locate Reply");
3676 if (locate_reply_tree == NULL)
3678 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3683 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3684 if (check_col(pinfo->cinfo, COL_INFO))
3686 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3688 if (locate_reply_tree)
3690 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3691 "Request id: %u", request_id);
3694 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3695 if (locate_reply_tree)
3697 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3698 "Locate status: %s",
3699 match_strval(locate_status, giop_locate_status_types)
3703 /* Decode the LocateReply body.
3705 * For GIOP 1.0 and 1.1 body immediately follows header.
3706 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3710 if (header->GIOP_version.minor > 1) {
3711 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3715 switch(locate_status) {
3716 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3717 case OBJECT_FORWARD_PERM:
3718 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3720 case LOC_SYSTEM_EXCEPTION:
3721 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3723 case LOC_NEEDS_ADDRESSING_MODE:
3724 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3725 if(locate_reply_tree) {
3726 proto_tree_add_text (tree, tvb, offset -2, 2,
3727 "AddressingDisposition: %u", addr_disp);
3730 default: /* others have no reply body */
3737 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3738 gboolean stream_is_big_endian)
3742 proto_tree *fragment_tree = NULL;
3747 tf = proto_tree_add_text (tree, tvb, offset, -1,
3748 "General Inter-ORB Fragment");
3749 if (fragment_tree == NULL)
3751 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3756 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3757 if (check_col(pinfo->cinfo, COL_INFO))
3759 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3763 proto_tree_add_uint (fragment_tree, hf_giop_req_id, tvb, offset-4, 4,request_id);
3769 /* Main entry point */
3771 gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3773 MessageHeader header;
3774 tvbuff_t *giop_header_tvb;
3775 tvbuff_t *payload_tvb;
3777 proto_tree *clnp_tree = NULL;
3780 guint minor_version;
3781 gboolean stream_is_big_endian;
3787 giop_dump_collection(cd_module_hash);
3788 giop_dump_collection(cd_objkey_hash);
3789 giop_dump_collection(cd_heuristic_users);
3790 giop_dump_collection(cd_complete_reply_hash);
3791 giop_dump_collection(cd_complete_request_list);
3794 header.exception_id = NULL;
3796 /* check magic number and version */
3799 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
3801 tot_len = tvb_length_remaining(tvb, 0);
3803 if (tot_len < GIOP_HEADER_SIZE)
3805 /* Not enough data captured to hold the GIOP header; don't try
3806 to interpret it as GIOP. */
3810 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3811 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3814 * because I have added extra elements in MessageHeader struct
3815 * for sub dissectors. -- FS
3818 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3820 if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
3822 /* Not a GIOP message. */
3827 if (check_col (pinfo->cinfo, COL_PROTOCOL))
3829 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3832 if (header.GIOP_version.major != GIOP_MAJOR ||
3833 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3835 /* Bad version number; should we note that and dissect the rest
3836 as data, or should we return FALSE on the theory that it
3837 might have been some other packet that happened to begin with
3838 "GIOP"? We shouldn't do *both*, so we return TRUE, for now.
3839 If we should return FALSE, we should do so *without* setting
3840 the "Info" column, *without* setting the "Protocol" column,
3841 and *without* adding anything to the protocol tree. */
3843 if (check_col (pinfo->cinfo, COL_INFO))
3845 col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3846 header.GIOP_version.major, header.GIOP_version.minor);
3850 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, tot_len, FALSE);
3851 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3852 proto_tree_add_text (clnp_tree, giop_header_tvb, 0, -1,
3853 "Version %u.%u not supported",
3854 header.GIOP_version.major,
3855 header.GIOP_version.minor);
3857 call_dissector(data_handle,payload_tvb, pinfo, tree);
3861 if (check_col (pinfo->cinfo, COL_INFO))
3863 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3864 header.GIOP_version.major, header.GIOP_version.minor,
3865 val_to_str(header.message_type, giop_message_types,
3866 "Unknown message type (0x%02x)"));
3869 stream_is_big_endian = is_big_endian (&header);
3871 if (stream_is_big_endian)
3872 message_size = pntohl (&header.message_size);
3874 message_size = pletohl (&header.message_size);
3878 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, tot_len, FALSE);
3879 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3880 proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3881 "Magic number: %s", GIOP_MAGIC);
3882 proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3884 header.GIOP_version.major,
3885 header.GIOP_version.minor);
3886 switch (minor_version)
3890 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3891 "Flags: 0x%02x (%s %s)",
3893 (stream_is_big_endian) ? "big-endian" : "little-endian",
3894 (header.flags & 0x02) ? " fragment" : "");
3897 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3898 "Byte ordering: %s-endian",
3899 (stream_is_big_endian) ? "big" : "little");
3903 } /* minor_version */
3905 proto_tree_add_uint_format (clnp_tree,
3906 hf_giop_message_type,
3907 giop_header_tvb, 7, 1,
3908 header.message_type,
3909 "Message type: %s", match_strval(header.message_type, giop_message_types));
3911 proto_tree_add_uint (clnp_tree,
3912 hf_giop_message_size,
3913 giop_header_tvb, 8, 4, message_size);
3918 if (check_col (pinfo->cinfo, COL_INFO))
3920 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3921 header.GIOP_version.major, header.GIOP_version.minor,
3922 match_strval(header.message_type, giop_message_types));
3926 switch (header.message_type)
3930 if(header.GIOP_version.minor < 2)
3932 dissect_giop_request_1_1 (payload_tvb, pinfo, tree,
3933 &header, stream_is_big_endian);
3937 dissect_giop_request_1_2 (payload_tvb, pinfo, tree,
3938 &header, stream_is_big_endian);
3945 if(header.GIOP_version.minor < 2)
3947 dissect_giop_reply (payload_tvb, pinfo, tree, &header,
3948 stream_is_big_endian);
3952 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree,
3953 &header, stream_is_big_endian);
3957 dissect_giop_cancel_request(payload_tvb, pinfo, tree,
3958 stream_is_big_endian);
3961 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
3962 stream_is_big_endian);
3965 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
3966 stream_is_big_endian);
3969 dissect_giop_fragment(payload_tvb, pinfo, tree,
3970 stream_is_big_endian);
3975 } /* switch message_type */
3979 * XXX - we should catch exceptions here, so that we can free
3980 * this if an exception is thrown.
3981 * We'd then have to forward the exception.
3983 if (header.exception_id != NULL)
3984 g_free(header.exception_id);
3990 proto_register_giop (void)
3992 static hf_register_info hf[] = {
3993 { &hf_giop_message_type,
3994 { "Message type", "giop.type",
3995 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
3998 { &hf_giop_message_size,
3999 { "Message size", "giop.len",
4000 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4004 { "Repository ID", "giop.repoid",
4005 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4008 { &hf_giop_string_length,
4009 { "String Length", "giop.strlen",
4010 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4013 { &hf_giop_sequence_length,
4014 { "Sequence Length", "giop.seqlen",
4015 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4018 { &hf_giop_profile_id,
4019 { "Profile ID", "giop.profid",
4020 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
4025 { "IOR::type_id", "giop.typeid",
4026 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4029 { &hf_giop_iiop_v_maj,
4030 { "IIOP Major Version", "giop.iiop_vmaj",
4031 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4034 { &hf_giop_iiop_v_min,
4035 { "IIOP Minor Version", "giop.iiop_vmin",
4036 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4039 { &hf_giop_endianess,
4040 { "Endianess", "giop.endianess",
4041 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4044 { &hf_giop_IIOP_tag,
4045 { "IIOP Component TAG", "giop.iioptag",
4046 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4050 { "IOR Profile TAG", "giop.iortag",
4051 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4055 { "TypeCode enum", "giop.TCKind",
4056 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4059 { &hf_giop_typecode_count,
4060 { "TypeCode count", "giop.tccount",
4061 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4064 { &hf_giop_typecode_default_used,
4065 { "default_used", "giop.tcdefault_used",
4066 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4069 { &hf_giop_typecode_digits,
4070 { "Digits", "giop.tcdigits",
4071 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4075 { &hf_giop_typecode_length,
4076 { "Length", "giop.tclength",
4077 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4080 { &hf_giop_typecode_max_length,
4081 { "Maximum length", "giop.tcmaxlen",
4082 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4085 { &hf_giop_typecode_member_name,
4086 { "TypeCode member name", "giop.tcmemname",
4087 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4090 { &hf_giop_typecode_name,
4091 { "TypeCode name", "giop.tcname",
4092 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4095 { &hf_giop_typecode_scale,
4096 { "Scale", "giop.tcscale",
4097 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4100 { &hf_giop_typecode_ValueModifier,
4101 { "ValueModifier", "giop.tcValueModifier",
4102 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4105 { &hf_giop_typecode_Visibility,
4106 { "Visibility", "giop.tcVisibility",
4107 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4112 { &hf_giop_type_boolean,
4113 { "TypeCode boolean data", "giop.tcboolean",
4114 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4117 { &hf_giop_type_char,
4118 { "TypeCode char data", "giop.tcchar",
4119 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4122 { &hf_giop_type_double,
4123 { "TypeCode double data", "giop.tcdouble",
4124 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4127 { &hf_giop_type_enum,
4128 { "TypeCode enum data", "giop.tcenumdata",
4129 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4133 * float as double ?? -- FIX
4136 { &hf_giop_type_float,
4137 { "TypeCode float data", "giop.tcfloat",
4138 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4141 { &hf_giop_type_long,
4142 { "TypeCode long data", "giop.tclongdata",
4143 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4146 { &hf_giop_type_octet,
4147 { "TypeCode octet data", "giop.tcoctet",
4148 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4151 { &hf_giop_type_short,
4152 { "TypeCode short data", "giop.tcshortdata",
4153 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4156 { &hf_giop_type_string,
4157 { "TypeCode string data", "giop.tcstring",
4158 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4161 { &hf_giop_type_ulong,
4162 { "TypeCode ulong data", "giop.tculongdata",
4163 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4166 { &hf_giop_type_ushort,
4167 { "TypeCode ushort data", "giop.tcushortdata",
4168 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4172 * IIOP Module - Chapter 15.10.2
4175 { &hf_giop_iiop_host,
4176 { "IIOP::Profile_host", "giop.iiop.host",
4177 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4181 { &hf_giop_iiop_port,
4182 { "IIOP::Profile_port", "giop.iiop.port",
4183 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4188 * IIOP ServiceContext
4191 { &hf_giop_iop_vscid,
4192 { "VSCID", "giop.iiop.vscid",
4193 FT_UINT32, BASE_HEX, NULL, 0xffffff00, "", HFILL }
4197 { &hf_giop_iop_scid,
4198 { "SCID", "giop.iiop.scid",
4199 FT_UINT32, BASE_HEX, NULL, 0x000000ff, "", HFILL }
4204 { "Request id", "giop.request_id",
4205 FT_UINT32, BASE_DEC, NULL, 0, "", HFILL }
4208 { &hf_giop_req_operation,
4209 { "Request operation", "giop.request_op",
4210 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4218 static gint *ett[] = {
4222 &ett_giop_cancel_request,
4223 &ett_giop_locate_request,
4224 &ett_giop_locate_reply,
4231 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4233 proto_register_field_array (proto_giop, hf, array_length (hf));
4234 proto_register_subtree_array (ett, array_length (ett));
4237 /* register init routine */
4239 register_init_routine( &giop_init); /* any init stuff */
4242 * Init the giop user module hash tables here, as giop users
4243 * will populate it via register_giop_user_module BEFORE my
4244 * own giop_init() is called.
4247 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4249 giop_module_keys = g_mem_chunk_new("giop_module_keys",
4250 sizeof(struct giop_module_key),
4251 giop_module_init_count * sizeof(struct giop_module_key),
4254 giop_module_vals = g_mem_chunk_new("giop_module_vals",
4255 sizeof(struct giop_module_val),
4256 giop_module_init_count * sizeof(struct giop_module_val),
4263 void proto_reg_handoff_giop (void) {
4264 data_handle = find_dissector("data");
4265 heur_dissector_add("tcp", dissect_giop, proto_giop);
4266 /* Support DIOP (GIOP/UDP) */
4267 heur_dissector_add("udp", dissect_giop, proto_giop);
4276 * Ref Corba v2.4.2 Chapter 13
4284 typedef unsigned long ProfileId;
4286 const ProfileId TAG_INTERNET_IOP = 0;
4287 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4289 struct TaggedProfile {
4291 sequence <octet> profile_data;
4296 sequence <TaggedProfile> profiles;
4299 typedef unsigned long ComponentId;
4301 struct TaggedComponent {
4303 sequence <octet> component_data;
4306 typedef sequence <TaggedComponent> MultipleComponentProfile;
4312 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4313 guint32 boundary, gboolean stream_is_big_endian) {
4316 guint32 seqlen_p; /* sequence length of profiles */
4319 proto_tree *tree = NULL; /* IOR tree */
4322 gchar *repobuf; /* for repository ID */
4326 /* create a subtree */
4329 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
4330 tree = proto_item_add_subtree (tf, ett_giop_ior);
4334 /* Get type_id == Repository ID */
4336 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4339 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4340 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4342 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4343 *offset-u_octet4,u_octet4,repobuf);
4348 * Register a cleanup function in case on of our tvbuff accesses
4349 * throws an exception. We need to clean up repobuf.
4350 * We can't free it yet, as we must wait until we have the object
4351 * key, as we have to add both to the hash table.
4353 CLEANUP_PUSH(g_free, repobuf);
4355 /* Now get a sequence of profiles */
4356 /* Get sequence length (number of elements) */
4358 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4360 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4361 *offset-sizeof(seqlen_p),4,seqlen_p);
4365 /* fetch all TaggedProfiles in this sequence */
4367 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4368 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4372 * We're done with repobuf, so we can call the cleanup handler to free
4373 * it, and then pop the cleanup handler.
4375 CLEANUP_CALL_AND_POP;
4379 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4380 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4382 guint32 seqlen_pd; /* sequence length of profile data */
4384 guint32 pidtag; /* profile ID TAG */
4386 gchar *profile_data; /* profile_data pointer */
4387 gchar *p_profile_data; /* printable profile_data pointer */
4389 guint32 new_boundary; /* for encapsulations encountered */
4390 gboolean new_big_endianess; /* for encapsulations encountered */
4392 /* Get ProfileId tag */
4394 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4397 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4398 *offset-sizeof(pidtag),4,pidtag);
4401 /* get sequence length, new endianness and boundary for encapsulation */
4403 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4404 stream_is_big_endian, boundary,
4405 &new_big_endianess, &new_boundary);
4407 /* return if zero length sequence */
4414 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4415 * decode it, otherwise just dump the octet sequence
4417 * also, store IOR in our objectkey hash
4419 * TODO - handle other TAGS
4423 case IOP_TAG_INTERNET_IOP:
4425 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4430 /* fetch all octets in this sequence , but skip endianess */
4432 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4434 /* Make a printable string */
4436 p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4439 proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4440 "Profile Data: %s", p_profile_data);
4443 g_free(p_profile_data);
4445 g_free(profile_data);
4456 * Decode IIOP IOR Profile
4457 * Ref Chap 15.7.2 in Corba Spec
4461 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4462 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4463 gboolean store_flag) {
4465 guint32 i; /* loop index */
4467 guint8 v_major,v_minor; /* IIOP sersion */
4469 guint32 u_octet4; /* u long */
4470 guint16 u_octet2; /* u short */
4471 guint32 seqlen; /* generic sequence length */
4472 guint32 seqlen1; /* generic sequence length */
4473 gchar *objkey; /* object key pointer */
4474 gchar *p_chars; /* printable characters pointer */
4477 /* Get major/minor version */
4479 v_major = get_CDR_octet(tvb,offset);
4480 v_minor = get_CDR_octet(tvb,offset);
4484 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4485 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4486 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4487 *offset-sizeof(v_minor),1,v_minor );
4493 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4496 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4497 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4499 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4500 *offset-u_octet4,u_octet4,buf);
4504 g_free(buf); /* dont forget */
4508 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4511 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4512 *offset-sizeof(u_octet2),2,u_octet2);
4516 /* Object Key - sequence<octet> object_key */
4518 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4521 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4522 *offset-sizeof(seqlen),4,seqlen);
4526 /* fetch all octets in this sequence */
4527 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4530 * Now we may have the Repository ID from earlier, as well
4531 * as the object key sequence and lengh. So lets store them in
4532 * our objectkey hash and free buffers.
4534 * But only insert if user is not clicking and repo id not NULL.
4540 if(!pinfo->fd->flags.visited)
4541 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4546 * No pinfo, but store anyway if flag set. eg: IOR read from file
4550 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4554 /* Make a printable string */
4556 p_chars = make_printable_string( objkey, seqlen );
4559 proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
4560 "Object Key: %s", p_chars);
4568 * Now see if if its v1.1 or 1.2, as they can contain
4569 * extra sequence of IOP::TaggedComponents
4582 /* sequence of IOP::TaggedComponents */
4583 /* Ref Chap 13 in Corba Spec */
4585 /* get sequence length */
4586 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4589 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4590 *offset-sizeof(seqlen),4,seqlen);
4593 for (i=0; i< seqlen; i++) {
4595 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4597 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4598 *offset-sizeof(u_octet4),4,u_octet4);
4601 /* get component_data */
4602 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4604 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4605 *offset-sizeof(seqlen1),4,seqlen1);
4609 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4612 /* Make a printable string of data */
4614 p_chars = make_printable_string(buf, seqlen1);
4616 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4617 "component_data: %s", p_chars);
4631 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4638 * From Section 13.10.2.5 of the CORBA 3.0 spec.
4640 * module CONV_FRAME {
4641 * typedef unsigned long CodeSetId;
4642 * struct CodeSetContext {
4643 * CodeSetId char_data;
4644 * CodeSetId wchar_data;
4648 * Code sets are identified by a 32-bit integer id from OSF.
4649 * See: ftp://ftp.opengroup.org/pub/code_set_registry
4651 static void decode_CodeSets(tvbuff_t *tvb, proto_tree *tree, int *offset,
4652 gboolean stream_is_be, guint32 boundary) {
4654 /* The boundary being passed in is the offset where the context_data
4655 * sequence begins. */
4657 guint32 code_set_id;
4659 /* We pass in -boundary, because the alignment is calculated relative to
4660 the beginning of the context_data sequence.
4661 Inside get_CDR_ulong(), the calculation will be (offset +(- boundary)) % 4
4662 to determine the correct alignment of the short. */
4663 code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
4665 proto_tree_add_text (tree, tvb, *offset - 4, 4,
4666 "char_data: 0x%08x", code_set_id);
4668 code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
4670 proto_tree_add_text (tree, tvb, *offset - 4, 4,
4671 "wchar_data: 0x%08x", code_set_id);
4677 * From Section 2.7.3 of the Real-time CORBA 1.1 Standard, the CORBA priority
4678 * is represented in the GIOP service request as:
4681 * typedef short ServiceId;
4682 * const ServiceId RTCorbaPriority = 10;
4685 * The RT-CORBA priority is a CDR encoded short value in a sequence<octet>
4688 static void decode_RTCorbaPriority(tvbuff_t *tvb, proto_tree *tree, int *offset,
4689 gboolean stream_is_be, guint32 boundary) {
4691 /* The boundary being passed in is the offset where the context_data
4692 * sequence begins. */
4696 /* RTCorbaPriority is stored as a CDR encoded short */
4697 /* We pass in -boundary, because the alignment is calculated relative to
4698 the beginning of the context_data sequence.
4699 Inside get_CDR_short(), the calculation will be (offset + (- boundary)) % 2
4700 to determine the correct alignment of the short. */
4701 rtpriority = get_CDR_short(tvb, offset, stream_is_be, -((gint32) boundary) );
4704 /* Highlight all of context_data except for the first endian byte */
4705 proto_tree_add_text (tree, tvb, *offset - 2, 2,
4706 "RTCorbaPriority: %d", rtpriority);
4711 static void decode_UnknownServiceContext(tvbuff_t *tvb, proto_tree *tree, int *offset,
4712 gboolean stream_is_be, guint32 boundary) {
4714 guint32 context_data_len;
4715 gchar *p_context_data;
4716 gchar *context_data;
4718 /* get sequence length, and NO encapsulation */
4719 context_data_len = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4722 /* return if zero length sequence */
4723 if(context_data_len == 0)
4727 * Now decode sequence according to vendor ServiceId, but I dont
4728 * have that yet, so just dump it as data.
4731 /* fetch all octets in this sequence */
4733 get_CDR_octet_seq(tvb, &context_data, offset, context_data_len);
4735 /* Make a printable string */
4737 p_context_data = make_printable_string( context_data, context_data_len );
4740 proto_tree_add_text (tree, tvb, *offset - context_data_len , context_data_len,
4741 "context_data: %s", p_context_data);
4744 g_free(context_data);
4745 g_free(p_context_data);
4753 * typedef unsigned long ServiceID;
4755 * struct ServiceContext {
4756 * ServiceID context_id;
4757 * sequence <octet> context_data;
4759 * typedef sequence <ServiceContext> ServiceContextList;
4762 * Note: Spec says context_data is an encapsulation.
4767 void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *ptree, int *offset,
4768 gboolean stream_is_be, guint32 boundary) {
4770 guint32 seqlen; /* sequence length */
4771 guint32 context_data_len; /* context data sequence length */
4773 proto_tree *tree = NULL; /* ServiceContext tree */
4774 proto_tree *sub_tree1 = NULL;
4775 proto_item *tf = NULL, *tf_st1;
4780 guint32 vscid; /* Vendor Service context id */
4782 const gchar *service_context_name;
4783 gboolean encapsulation_is_be;
4784 guint32 encapsulation_boundary;
4785 int temp_offset, temp_offset1;
4786 int start_offset = *offset;
4788 /* create a subtree */
4791 /* set length to 0 now and correct with proto_item_set_len() later */
4792 tf = proto_tree_add_text (ptree, tvb, *offset, 0, "ServiceContextList");
4794 tree = proto_item_add_subtree (tf, ett_giop_scl);
4797 /* Get sequence length (number of elements) */
4798 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4801 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4802 *offset-sizeof(seqlen),4,seqlen);
4805 /* return if zero length sequence */
4809 if (*offset - start_offset <= 0)
4810 THROW(ReportedBoundsError);
4811 proto_item_set_len(tf, *offset - start_offset);
4817 /* Loop for all ServiceContext's */
4819 for (i=0; i<seqlen; i++) {
4821 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4822 vscid = (context_id & 0xffffff00) >> 8; /* vendor info, top 24 bits */
4823 scid = context_id & 0x000000ff; /* standard service info, lower 8 bits */
4826 proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4827 *offset-sizeof(guint32),4,vscid);
4829 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4830 *offset-sizeof(guint32),4,scid);
4834 if( vscid == 0) { /* OMG specified */
4835 service_context_name = match_strval(scid, service_context_ids);
4836 } else { /* Proprietary vscid */
4837 service_context_name = NULL;
4840 if ( service_context_name == NULL ) {
4841 service_context_name = "Unknown";
4845 proto_tree_add_text (tree, tvb, *offset -sizeof(context_id), 4,
4846 "Service Context ID: %s (%u)", service_context_name,
4850 temp_offset1 = *offset;
4851 /* The OMG has vscid of 0 reserved */
4852 if( vscid != 0 || scid > max_service_context_id ) {
4853 decode_UnknownServiceContext(tvb, tree, offset, stream_is_be, boundary);
4857 temp_offset = *offset;
4858 /* get sequence length, new endianness and boundary for encapsulation */
4859 context_data_len = get_CDR_encap_info(tvb, sub_tree1, offset,
4860 stream_is_be, boundary,
4861 &encapsulation_is_be , &encapsulation_boundary);
4864 tf_st1 = proto_tree_add_text (tree, tvb, temp_offset, sizeof(context_data_len) + context_data_len , service_context_name);
4865 sub_tree1 = proto_item_add_subtree (tf_st1, ett_giop_scl_st1);
4868 if (context_data_len == 0)
4871 /* See CORBA 3.0.2 standard, section Section 15.3.3 "Encapsulation",
4872 * for how CDR types can be marshalled into a sequence<octet>.
4873 * The first octet in the sequence determines endian order,
4874 * 0 == big-endian, 1 == little-endian
4879 case 0x01: /* Codesets */
4880 decode_CodeSets(tvb, sub_tree1, offset,
4881 encapsulation_is_be, encapsulation_boundary);
4883 case 0x0a: /* RTCorbaPriority */
4884 decode_RTCorbaPriority(tvb, sub_tree1, offset,
4885 encapsulation_is_be, encapsulation_boundary);
4889 /* Need to fill these in as we learn them */
4890 *offset = temp_offset1;
4891 decode_UnknownServiceContext(tvb, sub_tree1, offset, stream_is_be,
4895 /* Set the offset to the end of the context_data sequence */
4896 *offset = temp_offset1 + sizeof(context_data_len) + context_data_len;
4901 if (*offset - start_offset <= 0)
4902 THROW(ReportedBoundsError);
4903 proto_item_set_len(tf, *offset - start_offset);
4908 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
4911 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
4912 gboolean stream_is_big_endian,
4915 guint32 length; /* string length */
4916 guint32 minor_code_value;
4917 guint32 completion_status;
4919 gchar *buf; /* pointer to string buffer */
4921 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
4924 proto_tree_add_text(tree, tvb, *offset-4, 4,
4925 "Exception length: %u", length);
4927 proto_tree_add_text(tree, tvb, *offset - length, length,
4928 "Exception id: %s", buf );
4933 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4934 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4937 proto_tree_add_text(tree, tvb, *offset-8, 4,
4938 "Minor code value: %u", minor_code_value);
4939 proto_tree_add_text(tree, tvb, *offset-4, 4,
4940 "Completion Status: %u", completion_status);
4946 * Helper functions for dissecting TypeCodes
4948 * These functions decode the complex parameter lists
4949 * of TypeCodes as defined in the CORBA spec chapter 15.
4952 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4953 gboolean stream_is_big_endian, guint32 boundary) {
4955 guint32 new_boundary; /* new boundary for encapsulation */
4956 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4958 guint32 seqlen; /* sequence length */
4960 /* get sequence length, new endianness and boundary for encapsulation */
4961 seqlen = get_CDR_encap_info(tvb, tree, offset,
4962 stream_is_big_endian, boundary,
4963 &new_stream_is_big_endian, &new_boundary);
4965 /* get repository ID */
4966 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4970 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4971 hf_giop_typecode_name);
4976 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4977 gboolean stream_is_big_endian, guint32 boundary,
4978 MessageHeader * header ) {
4980 guint32 new_boundary; /* new boundary for encapsulation */
4981 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4983 guint32 count; /* parameter count (of tuples) */
4984 guint32 seqlen; /* sequence length */
4985 guint32 i; /* loop index */
4987 /* get sequence lengt,h new endianness and boundary for encapsulation */
4988 seqlen = get_CDR_encap_info(tvb, tree, offset,
4989 stream_is_big_endian, boundary,
4990 &new_stream_is_big_endian, &new_boundary);
4992 /* get repository ID */
4993 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4997 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4998 hf_giop_typecode_name);
5000 /* get count of tuples */
5001 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5003 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5004 *offset-sizeof(count),4,count);
5007 /* get all tuples */
5008 for (i=0; i< count; i++) {
5009 /* get member name */
5010 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5011 hf_giop_typecode_member_name);
5013 /* get member type */
5014 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5020 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5021 gboolean stream_is_big_endian, guint32 boundary,
5022 MessageHeader * header) {
5024 guint32 new_boundary; /* new boundary for encapsulation */
5025 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5027 guint32 TCKind; /* TypeCode */
5028 gint32 s_octet4; /* signed int32 */
5030 guint32 count; /* parameter count (of tuples) */
5031 guint32 seqlen; /* sequence length */
5032 guint32 i; /* loop index */
5034 /* get sequence legnth, new endianness and boundary for encapsulation */
5035 seqlen = get_CDR_encap_info(tvb, tree, offset,
5036 stream_is_big_endian, boundary,
5037 &new_stream_is_big_endian, &new_boundary);
5039 /* get repository ID */
5040 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5044 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5045 hf_giop_typecode_name);
5047 /* get discriminant type */
5048 TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5050 /* get default used */
5051 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
5053 proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
5054 *offset-sizeof(s_octet4),4,s_octet4);
5056 /* get count of tuples */
5057 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5059 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5060 *offset-sizeof(count),4,count);
5063 /* get all tuples */
5064 for (i=0; i< count; i++) {
5065 /* get label value, based on TCKind above */
5066 dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
5068 /* get member name */
5069 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5070 hf_giop_typecode_member_name);
5072 /* get member type */
5073 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5079 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5080 gboolean stream_is_big_endian, guint32 boundary) {
5082 guint32 new_boundary; /* new boundary for encapsulation */
5083 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5085 guint32 count; /* parameter count (of tuples) */
5086 guint32 seqlen; /* sequence length */
5087 guint32 i; /* loop index */
5089 /* get sequence length, new endianness and boundary for encapsulation */
5090 seqlen = get_CDR_encap_info(tvb, tree, offset,
5091 stream_is_big_endian, boundary,
5092 &new_stream_is_big_endian, &new_boundary);
5094 /* get repository ID */
5095 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5099 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5100 hf_giop_typecode_name);
5102 /* get count of tuples */
5103 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5105 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5106 *offset-sizeof(count),4,count);
5109 /* get all tuples */
5110 for (i=0; i< count; i++) {
5111 /* get member name */
5112 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5113 hf_giop_typecode_member_name);
5119 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5120 gboolean stream_is_big_endian, guint32 boundary,
5121 MessageHeader * header) {
5123 guint32 new_boundary; /* new boundary for encapsulation */
5124 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5126 guint32 u_octet4; /* unsigned int32 */
5128 guint32 seqlen; /* sequence length */
5130 /* get sequence length, new endianness and boundary for encapsulation */
5131 seqlen = get_CDR_encap_info(tvb, tree, offset,
5132 stream_is_big_endian, boundary,
5133 &new_stream_is_big_endian, &new_boundary);
5135 /* get element type */
5136 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5138 /* get max length */
5139 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5141 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
5142 *offset-sizeof(u_octet4),4,u_octet4);
5147 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5148 gboolean stream_is_big_endian, guint32 boundary,
5149 MessageHeader * header) {
5151 guint32 new_boundary; /* new boundary for encapsulation */
5152 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5154 guint32 u_octet4; /* unsigned int32 */
5156 guint32 seqlen; /* sequence length */
5158 /* get sequence length, new endianness and boundary for encapsulation */
5159 seqlen = get_CDR_encap_info(tvb, tree, offset,
5160 stream_is_big_endian, boundary,
5161 &new_stream_is_big_endian, &new_boundary);
5163 /* get element type */
5164 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5167 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5169 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5170 *offset-sizeof(u_octet4),4,u_octet4);
5175 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5176 gboolean stream_is_big_endian, guint32 boundary,
5177 MessageHeader * header) {
5179 guint32 new_boundary; /* new boundary for encapsulation */
5180 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5182 guint32 seqlen; /* sequence length */
5184 /* get sequence legnth, new endianness and boundary for encapsulation */
5185 seqlen = get_CDR_encap_info(tvb, tree, offset,
5186 stream_is_big_endian, boundary,
5187 &new_stream_is_big_endian, &new_boundary);
5189 /* get repository ID */
5190 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5194 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5195 hf_giop_typecode_name);
5197 /* get ??? (noname) TypeCode */
5198 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5203 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5204 gboolean stream_is_big_endian, guint32 boundary,
5205 MessageHeader * header) {
5207 guint32 new_boundary; /* new boundary for encapsulation */
5208 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5210 guint32 count; /* parameter count (of tuples) */
5211 guint32 seqlen; /* sequence length */
5212 guint32 i; /* loop index */
5214 /* get sequence length, new endianness and boundary for encapsulation */
5215 seqlen = get_CDR_encap_info(tvb, tree, offset,
5216 stream_is_big_endian, boundary,
5217 &new_stream_is_big_endian, &new_boundary);
5219 /* get repository ID */
5220 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5224 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5225 hf_giop_typecode_name);
5227 /* get count of tuples */
5228 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5230 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5231 *offset-sizeof(count),4,count);
5234 /* get all tuples */
5235 for (i=0; i< count; i++) {
5236 /* get member name */
5237 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5238 hf_giop_typecode_member_name);
5240 /* get member type */
5241 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5247 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5248 gboolean stream_is_big_endian, guint32 boundary,
5249 MessageHeader * header) {
5251 guint32 new_boundary; /* new boundary for encapsulation */
5252 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5254 gint16 s_octet2; /* signed int16 */
5256 guint32 count; /* parameter count (of tuples) */
5257 guint32 seqlen; /* sequence length */
5258 guint32 i; /* loop index */
5260 /* get sequence length, new endianness and boundary for encapsulation */
5261 seqlen = get_CDR_encap_info(tvb, tree, offset,
5262 stream_is_big_endian, boundary,
5263 &new_stream_is_big_endian, &new_boundary);
5265 /* get repository ID */
5266 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5270 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5271 hf_giop_typecode_name);
5273 /* get ValueModifier */
5274 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5276 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5277 *offset-sizeof(s_octet2),2,s_octet2);
5280 /* get conrete base */
5281 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5283 /* get count of tuples */
5284 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5286 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5287 *offset-sizeof(count),4,count);
5290 /* get all tuples */
5291 for (i=0; i< count; i++) {
5292 /* get member name */
5293 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5294 hf_giop_typecode_member_name);
5296 /* get member type */
5297 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5299 /* get Visibility */
5300 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5302 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5303 *offset-sizeof(s_octet2),2,s_octet2);
5310 static void dissect_tk_value_box_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 seqlen; /* sequence length */
5319 /* get sequence length, new endianness and boundary for encapsulation */
5320 seqlen = get_CDR_encap_info(tvb, tree, offset,
5321 stream_is_big_endian, boundary,
5322 &new_stream_is_big_endian, &new_boundary);
5324 /* get repository ID */
5325 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5329 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5330 hf_giop_typecode_name);
5332 /* get ??? (noname) TypeCode */
5333 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5337 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5338 gboolean stream_is_big_endian, guint32 boundary) {
5340 guint32 new_boundary; /* new boundary for encapsulation */
5341 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5343 guint32 seqlen; /* sequence length */
5345 /* get sequence length, new endianness and boundary for encapsulation */
5346 seqlen = get_CDR_encap_info(tvb, tree, offset,
5347 stream_is_big_endian, boundary,
5348 &new_stream_is_big_endian, &new_boundary);
5350 /* get repository ID */
5351 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5355 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5356 hf_giop_typecode_name);
5361 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5362 gboolean stream_is_big_endian, guint32 boundary) {
5364 guint32 new_boundary; /* new boundary for encapsulation */
5365 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5367 guint32 seqlen; /* sequence length */
5369 /* get sequence length, new endianness and boundary for encapsulation */
5370 seqlen = get_CDR_encap_info(tvb, tree, offset,
5371 stream_is_big_endian, boundary,
5372 &new_stream_is_big_endian, &new_boundary);
5374 /* get repository ID */
5375 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5379 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5380 hf_giop_typecode_name);
5384 /* Typecode parameter lists are encoded as encapsulations and
5385 * this function gets the encapsulation information; see
5386 * CORBA spec chapter 15
5389 * Renamed to get_CDR_encap_info() for any encapsulation
5390 * we come across, useful helper function
5392 * Also, should return immediately if seqlen == 0.
5393 * ie: Forget about trying to grab endianess for
5394 * zero length sequence.
5396 * Caller must always check seqlen == 0, and not assume its value
5399 * Note: there seemed to be considerable confusion in corba
5400 * circles as to the correct interpretation of encapsulations,
5401 * and zero length sequences etc, but this is our best bet at the
5408 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5409 gboolean old_stream_is_big_endian, guint32 old_boundary,
5410 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5412 guint32 seqlen; /* sequence length */
5413 guint8 giop_endianess;
5415 /* Get sequence length of parameter list */
5416 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5418 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5419 *offset-sizeof(seqlen),4,seqlen);
5425 * seqlen == 0, implies no endianess and no data
5426 * so just return. Populate new_boundary_ptr and
5427 * new_stream_is_big_endian_ptr with current (old)
5428 * values, just to keep everyone happy. -- FS
5434 *new_boundary_ptr = old_boundary;
5435 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5441 /* Start of encapsulation of parameter list */
5442 *new_boundary_ptr = *offset; /* remember */
5443 giop_endianess = get_CDR_octet(tvb,offset);
5445 *new_stream_is_big_endian_ptr = ! giop_endianess;
5448 * Glib: typedef gint gboolean;
5449 * ie: It is not a guint8, so cannot use sizeof to correctly
5455 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5456 *offset-1,1,giop_endianess);
5466 * gets a TypeCode complex string parameter and
5467 * displays it in the relevant tree.
5470 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5471 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5473 guint32 u_octet4; /* unsigned int32 */
5474 gchar *buf; /* ptr to string buffer */
5477 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5480 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5481 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5483 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5487 g_free(buf); /* dont forget */
5492 * For a given data type, given by a TypeCode gets the associated data
5493 * and displays it in the relevant tree.
5496 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5497 gboolean stream_is_big_endian, guint32 boundary,
5498 MessageHeader * header, guint32 data_type ) {
5500 gboolean my_boolean; /* boolean */
5502 gint8 s_octet1; /* signed int8 */
5503 guint8 u_octet1; /* unsigned int8 */
5505 gint16 s_octet2; /* signed int16 */
5506 guint16 u_octet2; /* unsigned int16 */
5508 gint32 s_octet4; /* signed int32 */
5509 guint32 u_octet4; /* unsigned int32 */
5511 gdouble my_double; /* double */
5512 gfloat my_float; /* float */
5514 gchar *buf = NULL; /* ptr to string buffer */
5516 /* Grab the data according to data type */
5518 switch (data_type) {
5520 /* nothing to decode */
5523 /* nothing to decode */
5526 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5528 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5529 *offset-sizeof(s_octet2),2,s_octet2);
5533 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5535 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5536 *offset-sizeof(s_octet4),4,s_octet4);
5540 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5542 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5543 *offset-sizeof(u_octet2),2,u_octet2);
5547 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5549 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5550 *offset-sizeof(u_octet4),4,u_octet4);
5554 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5556 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5557 *offset-sizeof(my_float),4,my_float);
5561 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5563 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5564 *offset-sizeof(my_double),8,my_double);
5568 my_boolean = get_CDR_boolean(tvb,offset);
5570 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5571 *offset-1,1,my_boolean);
5575 u_octet1 = get_CDR_char(tvb,offset);
5577 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5578 *offset-sizeof(u_octet1),1,u_octet1);
5582 u_octet1 = get_CDR_octet(tvb,offset);
5584 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5585 *offset-sizeof(u_octet1),1,u_octet1);
5589 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5592 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5603 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5605 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5606 *offset-sizeof(u_octet4),4,u_octet4);
5610 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5612 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5613 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5615 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5616 *offset-u_octet4,u_octet4,buf);
5620 g_free(buf); /* dont forget */
5637 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5640 * XXX - can any of these throw an exception?
5641 * If so, we need to catch the exception and free "buf".
5643 if (s_octet1 < 0) { /* no size to add to tree */
5644 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5645 *offset+s_octet1,(-s_octet1),buf);
5647 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5648 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5649 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5650 *offset-s_octet1,s_octet1,buf);
5654 g_free(buf); /* dont forget */
5657 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5660 * XXX - can any of these throw an exception?
5661 * If so, we need to catch the exception and free "buf".
5663 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5664 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5665 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5666 *offset-u_octet4,u_octet4,buf);
5669 g_free(buf); /* dont forget */
5679 case tk_abstract_interface:
5682 g_warning("giop: Unknown typecode data type %u \n", data_type);