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 * Wireshark - Network traffic analyzer
15 * By Gerald Combs <gerald@wireshark.org>
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. Wireshark 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 Wireshark will have already done its first pass
271 * through the packets.
273 * Reload acts just like a normal Close/Open, except that it
274 * doesn't need to ask for a filename. So yes, the reload button
275 * clears the flags and re-dissects the file, just as if the file
276 * had been "opened". "
291 #ifdef NEED_STRERROR_H
292 #include "strerror.h"
297 #include <epan/packet.h>
298 #include <epan/conversation.h>
299 #include <epan/emem.h>
300 #include <epan/prefs.h>
302 #include "packet-giop.h"
303 #include "packet-tcp.h"
304 #include <wiretap/file_util.h>
308 * Set to 1 for DEBUG output - TODO make this a runtime option
314 * ------------------------------------------------------------------------------------------+
315 * Private Helper function Declarations
316 * ------------------------------------------------------------------------------------------+
320 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
321 guint32 boundary, gboolean new_endianess, gchar *repobuf,
322 gboolean store_flag);
324 static void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *tree, int *offset,
325 gboolean stream_is_be, guint32 boundary);
327 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
328 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf);
330 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
331 guint32 boundary, gboolean stream_is_big_endian );
333 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
334 gboolean stream_is_big_endian,
337 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
338 gboolean stream_is_big_endian, guint32 boundary);
340 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
341 gboolean stream_is_big_endian, guint32 boundary,
342 MessageHeader * header);
344 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
345 gboolean stream_is_big_endian, guint32 boundary,
346 MessageHeader * header );
348 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
349 gboolean stream_is_big_endian, guint32 boundary);
351 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
352 gboolean stream_is_big_endian, guint32 boundary,
353 MessageHeader * header);
355 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
356 gboolean stream_is_big_endian, guint32 boundary,
357 MessageHeader * header);
359 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
360 gboolean stream_is_big_endian, guint32 boundary,
361 MessageHeader * header);
363 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
364 gboolean stream_is_big_endian, guint32 boundary,
365 MessageHeader * header);
367 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
368 gboolean stream_is_big_endian, guint32 boundary,
369 MessageHeader * header);
371 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
372 gboolean stream_is_big_endian, guint32 boundary,
373 MessageHeader * header);
375 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
376 gboolean stream_is_big_endian, guint32 boundary);
378 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
379 gboolean stream_is_big_endian, guint32 boundary);
382 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
383 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
385 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
386 gboolean stream_is_big_endian, guint32 boundary,
387 MessageHeader * header, guint32 data_type );
393 * ------------------------------------------------------------------------------------------+
394 * Data/Variables/Structs
395 * ------------------------------------------------------------------------------------------+
399 static int proto_giop = -1;
400 static int hf_giop_message_type = -1;
401 static int hf_giop_message_size = -1;
402 static int hf_giop_repoid = -1;
403 static int hf_giop_req_id = -1;
404 static int hf_giop_req_operation = -1;
405 static int hf_giop_string_length = -1;
406 static int hf_giop_sequence_length = -1;
407 static int hf_giop_profile_id = -1;
408 static int hf_giop_type_id = -1;
409 static int hf_giop_iiop_v_maj = -1;
410 static int hf_giop_iiop_v_min = -1;
411 static int hf_giop_endianess = -1; /* esp encapsulations */
412 static int hf_giop_compressed = -1;
413 static int hf_giop_IOR_tag = -1;
414 static int hf_giop_IIOP_tag = -1;
416 static int hf_giop_TCKind = -1;
417 static int hf_giop_typecode_count = -1;
418 static int hf_giop_typecode_default_used = -1;
419 static int hf_giop_typecode_digits = -1;
420 static int hf_giop_typecode_length = -1;
421 static int hf_giop_typecode_max_length = -1;
422 static int hf_giop_typecode_member_name = -1;
423 static int hf_giop_typecode_name = -1;
424 static int hf_giop_typecode_scale = -1;
425 static int hf_giop_typecode_ValueModifier = -1;
426 static int hf_giop_typecode_Visibility = -1;
428 static int hf_giop_type_boolean = -1;
429 static int hf_giop_type_char = -1;
430 static int hf_giop_type_double = -1;
431 static int hf_giop_type_enum = -1;
432 static int hf_giop_type_float = -1;
433 static int hf_giop_type_long = -1;
434 static int hf_giop_type_octet = -1;
435 static int hf_giop_type_short = -1;
436 static int hf_giop_type_string = -1;
437 static int hf_giop_type_ulong = -1;
438 static int hf_giop_type_ushort = -1;
440 static int hf_giop_iiop_host = -1;
441 static int hf_giop_iiop_port = -1;
442 static int hf_giop_iop_vscid = -1;
443 static int hf_giop_iop_scid = -1;
445 static int hf_giop_reply_status = -1;
446 static int hf_giop_exception_id = -1;
447 static int hf_giop_objekt_key = -1;
453 static gint ett_giop = -1;
454 static gint ett_giop_reply = -1;
455 static gint ett_giop_request = -1;
456 static gint ett_giop_cancel_request = -1;
457 static gint ett_giop_locate_request = -1;
458 static gint ett_giop_locate_reply = -1;
459 static gint ett_giop_fragment = -1;
461 static gint ett_giop_scl = -1; /* ServiceContextList */
462 static gint ett_giop_scl_st1 = -1;
463 static gint ett_giop_ior = -1; /* IOR */
465 static dissector_handle_t data_handle;
466 static dissector_handle_t giop_tcp_handle;
469 static const value_string giop_endianess_vals[] = {
470 { 0x0, "Big Endian" },
471 { 0x1, "Little Endian" },
475 static const value_string sync_scope[] = {
476 { 0x0, "SYNC_NONE" },
477 { 0x1, "SYNC_WITH_TRANSPORT"},
478 { 0x2, "SYNC_WITH_SERVER"},
479 { 0x3, "SYNC_WITH_TARGET"},
485 static const value_string profile_id_vals[] = {
486 { 0x0, "TAG_INTERNET_IOP" },
487 { 0x1, "TAG_MULTIPLE_COMPONENTS"},
488 { 0x2, "TAG_SCCP_IOP"},
492 static const value_string giop_message_types[] = {
495 { 0x2, "CancelRequest"},
496 { 0x3, "LocateRequest"},
497 { 0x4, "LocateReply"},
498 { 0x5, "CloseConnection"},
499 { 0x6, "MessageError"},
504 static const value_string giop_locate_status_types[] = {
505 { 0x0, "Unknown Object" },
506 { 0x1, "Object Here"},
507 { 0x2, "Object Forward"},
508 { 0x3, "Object Forward Perm"},
509 { 0x4, "Loc System Exception"},
510 { 0x5, "Loc Needs Addressing Mode"},
514 static const value_string tckind_vals[] = {
527 { 12, "tk_TypeCode"},
528 { 13, "tk_Principal"},
534 { 19, "tk_sequence"},
538 { 23, "tk_longlong"},
539 { 24, "tk_ulonglong"},
540 { 25, "tk_longdouble"},
545 { 30, "tk_value_box"},
547 { 32, "tk_abstract_interface"},
552 * These values are taken from the CORBA 3.0.2 standard,
553 * section 13.7.1 "Standard Service Contexts".
555 static const guint32 max_service_context_id = 0x10;
556 static const value_string service_context_ids[] = {
557 { 0x00, "TransactionService" },
559 { 0x02, "ChainBypassCheck"},
560 { 0x03, "ChainBypassInfo"},
561 { 0x04, "LogicalThreadId"},
562 { 0x05, "BI_DIR_IIOP"},
563 { 0x06, "SendingContextRunTime"},
564 { 0x07, "INVOCATION_POLICIES"},
565 { 0x08, "FORWARDED_IDENTITY"},
566 { 0x09, "UnknownExceptionInfo"},
567 { 0x0a, "RTCorbaPriority"},
568 { 0x0b, "RTCorbaPriorityRange"},
569 { 0x0c, "FT_GROUP_VERSION"},
570 { 0x0d, "FT_REQUEST"},
571 { 0x0e, "ExceptionDetailMessage"},
572 { 0x0f, "SecurityAttributeService"},
573 { 0x10, "ActivityService"},
580 #define GIOP_MAGIC "GIOP"
583 * TAGS for IOR Profiles
585 * Chapter 13 Corba 2.4.2
589 #define IOP_TAG_INTERNET_IOP 0
590 #define IOP_TAG_MULTIPLE_COMPONENTS 1
593 /* Max Supported versions */
595 static const guint GIOP_MAJOR = 1;
596 static const guint GIOP_MINOR = 2;
599 static const value_string reply_status_types[] = {
600 { NO_EXCEPTION, "No Exception" } ,
601 { USER_EXCEPTION, "User Exception" } ,
602 { SYSTEM_EXCEPTION, "System Exception" } ,
603 { LOCATION_FORWARD, "Location Forward" } ,
604 { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
605 { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
611 typedef enum LocateStatusType
616 OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
617 LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
618 LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
622 typedef struct LocateReplyHeader
625 guint32 locate_status;
631 * DATA - complete_request_list
634 static GList *giop_complete_request_list;
636 struct comp_req_list_entry {
637 guint32 fn; /* frame number */
638 gchar * operation; /* echo echoString */
639 giop_sub_handle_t *subh; /* handle to sub dissector */
640 guint32 reqid; /* request id */
641 gchar * repoid; /* repository ID */
644 typedef struct comp_req_list_entry comp_req_list_entry_t;
648 * DATA - complete_reply_hash
650 * Maps reply FN to request MFN
653 struct complete_reply_hash_key {
654 guint32 fn; /* reply frame number */
657 struct complete_reply_hash_val {
658 guint32 mfn; /* matching frame number (request) */
661 GHashTable *giop_complete_reply_hash = NULL; /* hash */
664 * DATA - Module Hash stuff to store data from register_giop_user_module
666 * ie: module (or interface ?) name, and ptr to sub_dissector handle
668 * With this knowledge, we can call a sub dissector directly,
671 * objkey -> repoid -> sub_dissector via registered module/interface
676 struct giop_module_key {
677 gchar *module; /* module (interface?) name */
680 struct giop_module_val {
681 giop_sub_handle_t *subh; /* handle to sub dissector */
684 GHashTable *giop_module_hash = NULL; /* hash */
688 * DATA - GSList to store list of function (dissector) pointers.
689 * for heuristic dissection.
693 static GSList *giop_sub_list = NULL;
696 * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
697 * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
699 * With this knowledge, we can call a sub dissector directly later
702 * objkey -> repoid -> sub_dissector via registered module/interface
704 * rather than heuristic calls that do not provide operation context.
705 * (unless we pass the RepoID for a given objkey -- hmmm)
710 * Interesting operation list, add more if you want to save
714 static const char giop_op_resolve[] = "resolve";
715 static const char giop_op_bind_new_context[] _U_ = "bind_new_context";
716 static const char giop_op_bind[] _U_ = "bind";
717 static const char giop_op_is_a[] = "_is_a";
720 * Enums for interesting local operations, that we may need to monitor
721 * with their subsequent replies
726 request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
727 request_bind_new_context_op_val, /* bind_new_context */
728 request_bind_op_val, /* bind */
729 request_get_INIT_op_val /* finding Nameserver */
735 * hash for mapping object keys onto object namespaces, so
736 * I can call the correct dissector.
742 * Where did I get the IOR from.
746 req_res = 0, /* REQUEST (resolve) */
747 file /* stringified IOR' in a file */
751 typedef enum ior_src ior_src_t;
756 * Enums for my lists and hash's
759 enum collection_data {
760 cd_heuristic_users = 0,
763 cd_complete_request_list,
764 cd_complete_reply_hash
767 typedef enum collection_data collection_data_t;
771 struct giop_object_key {
772 guint8 *objkey; /* ptr to object key */
773 guint32 objkey_len; /* length */
776 struct giop_object_val {
777 guint8 *repo_id; /* ptr to Repository ID string */
778 ior_src_t src; /* where did Iget this IOR from */
781 GHashTable *giop_objkey_hash = NULL; /* hash */
784 gboolean giop_desegment = TRUE;
785 static const char *giop_ior_file = "IOR.txt";
788 * ------------------------------------------------------------------------------------------+
789 * Private helper functions
790 * ------------------------------------------------------------------------------------------+
796 * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
799 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
800 GList * newlist_start;
801 comp_req_list_entry_t * entry = NULL;
804 entry = g_malloc(sizeof(comp_req_list_entry_t));
805 opn = g_strdup(op); /* duplicate operation for storage */
808 entry->reqid = reqid;
810 entry->operation = opn;
811 entry->repoid = NULL; /* dont have yet */
813 newlist_start = g_list_append (list, entry); /* append */
815 return newlist_start;
820 * Used to find an entry with matching Frame Number FN
821 * in the complete_request_list list.
824 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
826 GList * element; /* entry in list */
827 comp_req_list_entry_t * entry_ptr = NULL;
829 element = g_list_last(giop_complete_request_list); /* start from last */
831 while(element) { /* valid list entry */
832 entry_ptr = element->data; /* grab data pointer */
833 if (entry_ptr->fn == fn) { /* similar FN */
836 element = g_list_previous(element); /* try next previous */
839 return NULL; /* no match so return NULL */
844 * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
846 * Call this when you know a FN and matching giop_sub_handle_t and repoid
848 * This is done in say, try_explicit_dissector for example.
852 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
854 comp_req_list_entry_t * entry = NULL;
855 entry = find_fn_in_list(fn); /* grab FN data entry */
859 entry->repoid = g_strdup(repoid); /* copy and store */
867 /* giop_complete_reply_hash "EQUAL" Functions */
869 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
870 const struct complete_reply_hash_key *mk1 = (const struct complete_reply_hash_key *)v;
871 const struct complete_reply_hash_key *mk2 = (const struct complete_reply_hash_key *)w;
873 if (mk1->fn == mk2->fn) {
877 return 0; /* found differences */
880 /* giop_complete_reply_hash "HASH" Functions */
882 static guint32 complete_reply_hash_fn(gconstpointer v) {
883 guint32 val; /* init hash value */
884 const struct complete_reply_hash_key *key = (const struct complete_reply_hash_key *)v;
886 val = key->fn; /* simple and unique */
893 * Insert the FN and MFN together in our complete_reply_hash.
896 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
898 struct complete_reply_hash_key key, *new_key;
899 struct complete_reply_hash_val *val = NULL;
903 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
906 return; /* FN collision */
909 new_key = se_alloc(sizeof(struct complete_reply_hash_key));
910 new_key->fn = fn; /* save FN */
912 val = se_alloc(sizeof(struct complete_reply_hash_val));
913 val->mfn = mfn; /* and MFN */
915 g_hash_table_insert(giop_complete_reply_hash, new_key, val);
920 * Find the MFN values from a given FN key.
921 * Assumes the complete_reply_hash is already populated.
924 static guint32 get_mfn_from_fn(guint32 fn) {
926 struct complete_reply_hash_key key;
927 struct complete_reply_hash_val *val = NULL;
928 guint32 mfn = fn; /* save */
931 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
934 mfn = val->mfn; /* grab it */
937 return mfn; /* mfn or fn if not found */
942 * Attempt to find the MFN for this FN, and return it.
943 * Return MFN if found, or just FN if not. This is
944 * only used when we are building
947 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
949 GList * element; /* last entry in list */
950 comp_req_list_entry_t * entry_ptr = NULL;
952 /* Need Some pretty snappy code */
954 /* Loop back from current end of complete_request_list looking for */
955 /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
958 * As this routine is only called during initial pass of data,
959 * and NOT when a user clicks, it is ok to start from Current
960 * end of complete_request_list when searching for a match.
961 * As that list is bing populated in the same order as FN's
964 * Also, can make check for same reqid more detailed, but I start
965 * with reqid. Could add say port or address checks etc later ??
969 element = g_list_last(giop_complete_request_list); /* get last */
971 while(element) { /* valid list entry */
972 entry_ptr = element->data; /* grab data pointer */
973 if (entry_ptr->reqid == reqid) { /* similar reqid */
974 return entry_ptr->fn; /* return MFN */
976 element = g_list_previous(element); /* try next previous */
979 return fn; /* no match so return FN */
983 /* Module Hash "EQUAL" Functions */
985 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
986 const struct giop_module_key *mk1 = (const struct giop_module_key *)v;
987 const struct giop_module_key *mk2 = (const struct giop_module_key *)w;
989 if (strcmp(mk1->module, mk2->module) == 0) {
993 return 0; /* found differences */
996 /* Module Hash "HASH" Functions */
998 static guint32 giop_hash_module_hash(gconstpointer v) {
1001 guint32 val = 0; /* init hash value */
1003 const struct giop_module_key *key = (const struct giop_module_key *)v;
1006 * Hmm, try this simple hashing scheme for now.
1007 * ie: Simple summation, FIX later -- FS
1012 len = strlen(key->module);
1014 for (i=0; i<len; i++) {
1015 val += (guint8) key->module[i];
1024 * ------------------------------------------------------------------------------------------+
1025 * Public Utility functions
1026 * ------------------------------------------------------------------------------------------+
1033 * Routine to allow giop users to register their sub dissector function, name, and
1034 * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1035 * value returned from their proto_register_protocol(), so we can enable/disbale it
1036 * through the GUI (edit protocols).
1038 * This is used by try_explicit_giop_dissector() to find the
1039 * correct sub-dissector.
1043 void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
1045 struct giop_module_key module_key, *new_module_key;
1046 struct giop_module_val *module_val = NULL;
1048 module_key.module = module; /* module name */
1050 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1053 return; /* module name collision */
1056 /* So, passed module name should NOT exist in hash at this point.*/
1059 printf("giop:register_module: Adding Module %s to module hash \n", module);
1060 printf("giop:register_module: Module sub dissector name is %s \n", name);
1063 new_module_key = g_malloc(sizeof(struct giop_module_key));
1064 new_module_key->module = module; /* save Module or interface name from IDL */
1066 module_val = g_malloc(sizeof(struct giop_module_val));
1068 module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
1070 module_val->subh->sub_name = name; /* save dissector name */
1071 module_val->subh->sub_fn = sub; /* save subdissector*/
1072 module_val->subh->sub_proto = find_protocol_by_id(sub_proto); /* save protocol_t for subdissector's protocol */
1074 g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1081 /* Object Key Hash "EQUAL" Functions */
1083 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1084 const struct giop_object_key *v1 = (const struct giop_object_key *)v;
1085 const struct giop_object_key *v2 = (const struct giop_object_key *)w;
1087 if (v1->objkey_len != v2->objkey_len)
1088 return 0; /* no match because different length */
1090 /* Now do a byte comaprison */
1092 if (memcmp(v1->objkey,v2->objkey, v1->objkey_len) == 0) {
1093 return 1; /* compares ok */
1097 printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1100 return 0; /* found differences */
1103 /* Object Key Hash "HASH" Functions */
1105 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1106 const struct giop_object_key *key = (const struct giop_object_key *)v;
1109 guint32 val = 0; /* init hash value */
1113 * Hmm, try this simple hashing scheme for now.
1114 * ie: Simple summation
1120 printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1123 for (i=0; i< key->objkey_len; i++) {
1124 val += (guint8) key->objkey[i];
1132 * Routine to take an object key octet sequence, and length, and ptr to
1133 * a (null terminated )repository ID string, and store them in the obect key hash.
1135 * Blindly Inserts even if it does exist, See TODO at top for reason.
1138 static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
1140 struct giop_object_key objkey_key, *new_objkey_key;
1141 struct giop_object_val *objkey_val = NULL;
1143 objkey_key.objkey_len = len; /* length */
1144 objkey_key.objkey = obj; /* object key octet sequence */
1146 /* Look it up to see if it exists */
1148 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1150 /* CHANGED -- Same reqid, so abandon old entry */
1153 g_hash_table_remove(hash, &objkey_key);
1156 /* So, passed key should NOT exist in hash at this point.*/
1158 new_objkey_key = se_alloc(sizeof(struct giop_object_key));
1159 new_objkey_key->objkey_len = len; /* save it */
1160 new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */
1162 objkey_val = se_alloc(sizeof(struct giop_object_val));
1163 objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
1164 objkey_val->src = src; /* where IOR came from */
1168 printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
1169 objkey_val->repo_id, new_objkey_key->objkey_len);
1172 g_hash_table_insert(hash, new_objkey_key, objkey_val);
1179 * convert an ascii char representing a hex value,
1180 * to a numeric value.
1182 * returns value, or -1 if problem.
1186 static gint8 hex_char_to_val(guchar c){
1193 retval = c - 48; /* convert digit */
1197 c = toupper(c); /* convert to uppercase */
1198 if (c >= 'A' && c <= 'F') {
1209 * Convert from stringified IOR of the kind IOR:af4f7e459f....
1210 * to an IOR octet sequence.
1212 * User must free buffer.
1214 * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1215 * grab repoid etc for our objkey hash.
1219 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1222 gint8 tmpval; /* complete value */
1225 *out = g_new0(guint8, in_len); /* allocate buffer */
1231 /* skip past IOR: and convert character pairs to guint8 */
1233 for (i=4; i<in_len-1; i+=2) {
1234 if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1236 if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1237 g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1241 if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1242 g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1245 tmpval = tmpval_msb << 4;
1246 tmpval += tmpval_lsb;
1247 (*out)[(i-4)/2] = (guint8) tmpval;
1257 return (i-4)/2; /* length */
1264 * Simple "get a line" routine, copied from somewhere :)
1268 static int giop_getline(FILE *fp, gchar *line, int maxlen) {
1270 if (fgets(line,maxlen,fp) == NULL)
1273 return strlen(line);
1279 * Read a list of stringified IOR's from a named file, convert to IOR's
1280 * and store in object key hash
1283 static void read_IOR_strings_from_file(const gchar *name, int max_iorlen) {
1284 guchar *buf; /* NOTE reused for every line */
1286 int ior_val_len; /* length after unstringifying. */
1288 guint8 *out; /* ptr to unstringified IOR */
1289 tvbuff_t *tvb; /* temp tvbuff for dissectin IORs */
1290 guint32 my_offset = 0;
1291 gboolean stream_is_big_endian;
1294 fp = eth_fopen(name,"r"); /* open read only */
1297 if (errno == EACCES)
1298 fprintf(stderr, "Error opening file %s for reading: %s\n", name, strerror(errno));
1302 buf = g_malloc0(max_iorlen+1); /* input buf */
1304 while ((len = giop_getline(fp,buf,max_iorlen+1)) > 0) {
1305 my_offset = 0; /* reset for every IOR read */
1307 ior_val_len = string_to_IOR(buf,len,&out); /* convert */
1311 /* Combination of tvb_new() and tvb_set_real_data().
1312 Can throw ReportedBoundsError.
1314 XXX - can it throw an exception in this case? If so, we
1315 need to catch it and clean up, but we really shouldn't allow
1316 it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
1319 tvb = tvb_new_real_data(out, ior_val_len, ior_val_len);
1321 stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1322 decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1332 fclose(fp); /* be nice */
1340 * Init routine, setup our request hash stuff, or delete old ref's
1342 * Cannot setup the module hash here as my init() may not be called before
1343 * users start registering. So I will move the module_hash stuff to
1344 * proto_register_giop, as is done with packet-rpc
1348 * Also, setup our objectkey/repoid hash here.
1352 static void giop_init(void) {
1356 * Create objkey/repoid hash, use my "equal" and "hash" functions.
1360 if (giop_objkey_hash)
1361 g_hash_table_destroy(giop_objkey_hash);
1364 * Create hash, use my "equal" and "hash" functions.
1368 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1371 * Create complete_reply_hash, use my "equal" and "hash" functions.
1375 if (giop_complete_reply_hash)
1376 g_hash_table_destroy(giop_complete_reply_hash);
1380 * Create hash, use my "equal" and "hash" functions.
1384 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1387 read_IOR_strings_from_file(giop_ior_file, 600);
1394 * Insert an entry in the GIOP Heuristic User table.
1396 * Uses giop_sub_handle_t to wrap giop user info.
1400 void register_giop_user(giop_sub_dissector_t *sub, const gchar *name, int sub_proto) {
1402 giop_sub_handle_t *subh;
1404 subh = g_malloc(sizeof (giop_sub_handle_t));
1406 subh->sub_name = name;
1408 subh->sub_proto = find_protocol_by_id(sub_proto); /* protocol_t for sub dissectors's proto_register_protocol() */
1410 giop_sub_list = g_slist_append (giop_sub_list, subh);
1416 * Lookup an object key in our object key hash, and return the corresponding
1421 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1423 struct giop_object_key objkey_key;
1424 struct giop_object_val *objkey_val = NULL;
1426 objkey_key.objkey_len = len; /* length */
1427 objkey_key.objkey = obj; /* object key octet sequence */
1429 /* Look it up to see if it exists */
1431 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1435 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1437 return objkey_val->repo_id; /* found */
1441 printf("FAILED Lookup of object key \n" );
1444 return NULL; /* not found */
1450 * Extract top level module/interface from repoid
1452 * eg from - "IDL:Echo/interface1:1.0"
1455 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1456 * get linux.org/Penguin/Teeth
1459 * User must free returned ptr after use.
1461 * TODO -- generalize for other Repoid encodings
1464 static gchar * get_modname_from_repoid(gchar *repoid) {
1466 gchar *modname = NULL;
1467 gchar *saved_repoid = NULL;
1469 guint8 stop_mod = 0; /* Index of last character of modname in Repoid */
1470 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1473 saved_repoid = g_strdup(repoid); /* make a copy */
1475 /* Must start with IDL: , otherwise I get confused */
1477 if (g_ascii_strncasecmp("IDL:",repoid,4))
1480 /* Looks like a RepoID to me, so get Module or interface name */
1482 /* TODO -- put some code here to get Module name */
1484 for(i=4; c != '\0'; i++) {
1486 stop_mod = i; /* save */
1487 if (c == ':' ) /* delimiters */
1492 /* Now create a new string based on start and stop and \0 */
1494 modname = g_strndup(repoid+4, stop_mod - start_mod);
1509 * Display a "module" hash entry
1512 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1514 struct giop_module_val *mv = (struct giop_module_val *) val;
1515 struct giop_module_key *mk = (struct giop_module_key *) key;
1517 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1524 * Display a "complete_reply " hash entry
1527 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1529 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1530 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1532 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1540 * Display an "objkey" hash entry
1543 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1545 struct giop_object_val *mv = (struct giop_object_val *) val;
1546 struct giop_object_key *mk = (struct giop_object_key *) key;
1549 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1551 for (i=0; i<mk->objkey_len; i++) {
1552 printf("%.2x ", mk->objkey[i]);
1556 * If read from file, mark it as such..
1560 printf(", Repo ID = %s \n", mv->repo_id);
1563 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1571 * Display all giop_sub_list (GSList) entries
1574 static void display_heuristic_user_list() {
1577 giop_sub_handle_t *subh; /* handle */
1579 /* Get length of list */
1580 len = g_slist_length(giop_sub_list); /* find length */
1585 for (i=0; i<len; i++) {
1586 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1587 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1593 * Display all complete_request_list (GList) entries
1596 static void display_complete_request_list() {
1599 comp_req_list_entry_t *entry;
1601 /* Get length of list */
1602 len = g_list_length(giop_complete_request_list); /* find length */
1607 for (i=0; i<len; i++) {
1608 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1609 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1610 entry->reqid,entry->operation, entry->repoid);
1618 /* Dump Hash/List contents
1620 * collection_type specifies the list or hash to dump
1624 static void giop_dump_collection(collection_data_t collection_type) {
1626 switch(collection_type) {
1627 case cd_heuristic_users:
1628 printf("+----------------------------------------------+ \n");
1629 printf("+-------------- Heuristic User (Begin) --------+ \n");
1630 printf("+----------------------------------------------+ \n");
1632 display_heuristic_user_list();
1634 printf("+----------------------------------------------+ \n");
1635 printf("+-------------- Heuristic User (End) ----------+ \n");
1636 printf("+----------------------------------------------+ \n");
1640 case cd_complete_request_list:
1641 printf("+----------------------------------------------+ \n");
1642 printf("+------------- Complete Request List (Begin) --+ \n");
1643 printf("+----------------------------------------------+ \n");
1645 display_complete_request_list();
1647 printf("+----------------------------------------------+ \n");
1648 printf("+------------ Complete Request List (End) -----+ \n");
1649 printf("+----------------------------------------------+ \n");
1653 case cd_module_hash:
1654 printf("+----------------------------------------------+ \n");
1655 printf("+-------------- Module (Begin) ----------------+ \n");
1656 printf("+----------------------------------------------+ \n");
1658 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1660 printf("+----------------------------------------------+ \n");
1661 printf("+-------------- Module ( End) -----------------+ \n");
1662 printf("+----------------------------------------------+ \n\n");
1666 case cd_objkey_hash:
1667 printf("+----------------------------------------------+ \n");
1668 printf("+-------------- Objkey (Begin) ----------------+ \n");
1669 printf("+----------------------------------------------+ \n");
1671 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1673 printf("+----------------------------------------------+ \n");
1674 printf("+-------------- Objkey (End) ------------------+ \n");
1675 printf("+----------------------------------------------+ \n\n");
1679 case cd_complete_reply_hash:
1680 printf("+----------------------------------------------+ \n");
1681 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1682 printf("+----------------------------------------------+ \n");
1684 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1686 printf("+----------------------------------------------+ \n");
1687 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1688 printf("+----------------------------------------------+ \n");
1694 printf("giop: giop_dump_collection: Unknown type \n");
1705 * Loop through all subdissectors, and call them until someone
1706 * answers (returns TRUE). This function then returns TRUE, otherwise
1709 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1712 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1713 MessageHeader *header, gchar *operation ) {
1716 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1717 giop_sub_handle_t *subh = NULL;
1718 const char *saved_proto;
1720 len = g_slist_length(giop_sub_list); /* find length */
1725 saved_proto = pinfo->current_proto;
1726 for (i=0; i<len; i++) {
1727 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1729 if (proto_is_protocol_enabled(subh->sub_proto)) {
1730 pinfo->current_proto =
1731 proto_get_protocol_short_name(subh->sub_proto);
1732 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1734 pinfo->current_proto = saved_proto;
1735 return TRUE; /* found one, lets return */
1737 } /* protocol_is_enabled */
1740 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1741 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
1743 pinfo->current_proto = saved_proto;
1744 return res; /* result */
1750 * Find the matching repoid in the module hash and call
1751 * the dissector function if offset exists.
1754 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1755 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1761 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1762 MessageHeader *header, gchar *operation, gchar *repoid ) {
1764 giop_sub_handle_t *subdiss = NULL; /* handle */
1765 gboolean res = FALSE;
1766 gchar *modname = NULL;
1767 struct giop_module_key module_key;
1768 struct giop_module_val *module_val = NULL;
1769 const char *saved_proto;
1773 * Get top level module/interface from complete repoid
1776 modname = get_modname_from_repoid(repoid);
1777 if (modname == NULL) {
1778 return res; /* unknown module name */
1782 /* Search for Module or interface name */
1784 module_key.module = modname; /* module name */
1785 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1787 if (module_val == NULL) {
1788 return res; /* module not registered */
1791 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1794 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1795 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1796 /* but only if user not clicking */
1798 if (!pinfo->fd->flags.visited)
1799 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1802 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1804 if (tvb_offset_exists(tvb, *offset)) {
1806 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1809 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1811 saved_proto = pinfo->current_proto;
1812 pinfo->current_proto =
1813 proto_get_protocol_short_name(subdiss->sub_proto);
1814 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1815 pinfo->current_proto = saved_proto;
1817 } /* protocol_is_enabled */
1818 } /* offset exists */
1821 return res; /* return result */
1826 /* Take in an array of char and create a new string.
1827 * Replace non-printable characters with periods.
1829 * The array may contain \0's so dont use strdup
1830 * The string is \0 terminated, and thus longer than
1831 * the initial sequence.
1832 * Caller must free the new string.
1835 gchar * make_printable_string (gchar *in, guint32 len) {
1837 gchar *print_string = NULL;
1839 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1840 memcpy(print_string, in, len); /* and make a copy of input data */
1842 for(i=0; i < len; i++) {
1843 if( !isprint( (unsigned char)print_string[i] ) )
1844 print_string[i] = '.';
1847 return print_string; /* return ptr */
1850 /* Determine the byte order from the GIOP MessageHeader */
1852 gboolean is_big_endian (MessageHeader * header) {
1853 gboolean big_endian = FALSE;
1855 switch (header->GIOP_version.minor) {
1858 if (header->flags & 0x01)
1878 * Calculate new offset, based on the current offset, and user supplied
1879 * "offset delta" value, and the alignment requirement.
1883 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1884 * aligned on 8 byte boundaries.
1887 static void set_new_alignment(int *offset, int delta, int alignment) {
1889 while( ( (*offset + delta) % alignment) != 0)
1898 * ------------------------------------------------------------------------------------------+
1899 * Public get_CDR_xxx functions.
1900 * ------------------------------------------------------------------------------------------+
1906 * Gets data of type any. This is encoded as a TypeCode
1907 * followed by the encoded value.
1910 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1911 gboolean stream_is_big_endian, int boundary,
1912 MessageHeader * header ) {
1914 guint32 TCKind; /* TypeCode */
1916 /* get TypeCode of any */
1917 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1919 /* dissect data of type TCKind */
1920 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1924 /* Copy a 1 octet sequence from the tvbuff
1925 * which represents a boolean value, and convert
1926 * it to a boolean value.
1927 * Offset is then incremented by 1, to indicate the 1 octet which
1928 * has been processed.
1931 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1934 val = tvb_get_guint8(tvb, *offset); /* easy */
1939 /* Copy a 1 octet sequence from the tvbuff
1940 * which represents a char, and convert
1941 * it to an char value.
1942 * offset is then incremented by 1, to indicate the 1 octet which
1943 * has been processed.
1946 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1949 val = tvb_get_guint8(tvb, *offset); /* easy */
1957 * Floating Point Data Type double IEEE 754-1985
1959 * Copy an 8 octet sequence from the tvbuff
1960 * which represents a double value, and convert
1961 * it to a double value, taking into account byte order.
1962 * offset is first incremented so that it falls on a proper alignment
1963 * boundary for double values.
1964 * offset is then incremented by 8, to indicate the 8 octets which
1965 * have been processed.
1968 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1972 /* double values must be aligned on a 8 byte boundary */
1974 while( ( (*offset + boundary) % 8) != 0)
1977 val = (stream_is_big_endian) ? tvb_get_ntohieee_double (tvb, *offset) :
1978 tvb_get_letohieee_double (tvb, *offset);
1986 /* Copy a 4 octet sequence from the tvbuff
1987 * which represents an enum value, and convert
1988 * it to an enum value, taking into account byte order.
1989 * offset is first incremented so that it falls on a proper alignment
1990 * boundary for an enum (4)
1991 * offset is then incremented by 4, to indicate the 4 octets which
1992 * have been processed.
1994 * Enum values are encoded as unsigned long.
1998 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2000 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2006 * Copy an octet sequence from the tvbuff
2007 * which represents a Fixed point decimal type, and create a string representing
2008 * a Fixed point decimal type. There are no alignment restrictions.
2009 * Size and scale of fixed decimal type is determined by IDL.
2011 * digits - IDL specified number of "digits" for this fixed type
2012 * scale - IDL specified "scale" for this fixed type
2015 * eg: typedef fixed <5,2> fixed_t;
2016 * could represent numbers like 123.45, 789.12,
2019 * As the fixed type could be any size, I will not try to fit it into our
2020 * simple types like gdouble or glong etc. I will just create a string buffer holding
2021 * a representation (after scale is applied), and with a decimal point or zero padding
2022 * inserted at the right place if necessary. The string is null terminated
2024 * so string may look like
2027 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2029 * According to spec, digits <= 31
2030 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2033 * User must remember to free the buffer
2038 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2040 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2041 guint32 i ; /* loop */
2042 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2043 /* this does not include sign, decimal point and \0 */
2044 guint32 sindex = 0; /* string index */
2045 gchar *tmpbuf; /* temp buff, holds string without scaling */
2046 guint8 tval; /* temp val storage */
2049 * how many bytes to hold digits and scale (if scale <0)
2051 * eg: fixed <5,2> = 5 digits
2052 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2056 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2060 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2062 slen = digits; /* digits */
2066 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2069 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2072 * Register a cleanup function in case on of our tvbuff accesses
2073 * throws an exception. We need to clean up tmpbuf.
2075 CLEANUP_PUSH(g_free, tmpbuf);
2077 /* If even , grab 1st dig */
2079 if (!(digits & 0x01)) {
2080 tval = get_CDR_octet(tvb,offset);
2082 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2084 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2089 * Loop, but stop BEFORE we hit last digit and sign
2090 * if digits = 1 or 2, then this part is skipped
2094 for(i=0; i< ((digits-1)/2 ); i++) {
2095 tval = get_CDR_octet(tvb,offset);
2097 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2100 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2102 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2109 printf("giop:get_CDR_fixed(): before last digit \n");
2113 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2115 tval = get_CDR_octet(tvb,offset);
2117 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2119 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2122 sign = tval & 0x0f; /* get sign */
2124 /* So now, we have all digits in an array, and the sign byte
2125 * so lets generate a printable string, taking into account the scale
2129 sindex = 0; /* reset */
2130 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2131 * \0 -- TODO check slen is reasonable first */
2133 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2138 (*seq)[sindex] = '+'; /* put sign in first string position */
2141 (*seq)[sindex] = '-';
2144 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2145 (*seq)[sindex] = '*'; /* flag as sign unkown */
2151 /* Add decimal point or padding 0's, depending if scale is positive or
2152 * negative, respectively
2156 for (i=0; i<digits-scale; i++) {
2157 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2161 (*seq)[sindex] = '.'; /* decimal point */
2164 for (i=digits-scale; i<digits; i++) {
2165 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2169 (*seq)[sindex] = '\0'; /* string terminator */
2173 /* negative scale, dump digits and pad out with 0's */
2175 for (i=0; i<digits-scale; i++) {
2177 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2179 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2184 (*seq)[sindex] = '\0'; /* string terminator */
2189 * We're done with tmpbuf, so we can call the cleanup handler to free
2190 * it, and then pop the cleanup handler.
2192 CLEANUP_CALL_AND_POP;
2195 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2205 * Floating Point Data Type float IEEE 754-1985
2207 * Copy an 4 octet sequence from the tvbuff
2208 * which represents a float value, and convert
2209 * it to a float value, taking into account byte order.
2210 * offset is first incremented so that it falls on a proper alignment
2211 * boundary for float values.
2212 * offset is then incremented by 4, to indicate the 4 octets which
2213 * have been processed.
2216 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2220 /* float values must be aligned on a 4 byte boundary */
2222 while( ( (*offset + boundary) % 4) != 0)
2225 val = (stream_is_big_endian) ? tvb_get_ntohieee_float (tvb, *offset) :
2226 tvb_get_letohieee_float (tvb, *offset);
2235 * Decode an Interface type, and display it on the tree.
2238 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2239 gboolean stream_is_big_endian, int boundary) {
2242 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2248 /* Copy a 4 octet sequence from the tvbuff
2249 * which represents a signed long value, and convert
2250 * it to an signed long vaule, taking into account byte order.
2251 * offset is first incremented so that it falls on a proper alignment
2252 * boundary for long values.
2253 * offset is then incremented by 4, to indicate the 4 octets which
2254 * have been processed.
2257 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2261 /* unsigned long values must be aligned on a 4 byte boundary */
2262 while( ( (*offset + boundary) % 4) != 0)
2265 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2266 tvb_get_letohl (tvb, *offset);
2272 /* Copy a 8 octet sequence from the tvbuff
2273 * which represents a signed long long value, and convert
2274 * it to an signed long long vaule, taking into account byte order.
2275 * offset is first incremented so that it falls on a proper alignment
2276 * boundary for long long values.
2277 * offset is then incremented by 8, to indicate the 8 octets which
2278 * have been processed.
2281 gint64 get_CDR_long_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2285 /* unsigned long long values must be aligned on a 8 byte boundary */
2286 while( ( (*offset + boundary) % 8) != 0)
2289 val = (stream_is_big_endian) ? tvb_get_ntoh64 (tvb, *offset) :
2290 tvb_get_letoh64 (tvb, *offset);
2297 * Decode an Object type, and display it on the tree.
2300 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2301 gboolean stream_is_big_endian, int boundary) {
2303 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2309 /* Copy a 1 octet sequence from the tvbuff
2310 * which represents a octet, and convert
2311 * it to an octet value.
2312 * offset is then incremented by 1, to indicate the 1 octet which
2313 * has been processed.
2316 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2319 val = tvb_get_guint8(tvb, *offset); /* easy */
2325 /* Copy a sequence of octets from the tvbuff.
2326 * Caller of this function must remember to free the
2327 * array pointed to by seq.
2328 * This function also increments offset by len.
2331 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, guint32 len) {
2334 * Make sure that the entire sequence of octets is in the buffer before
2335 * allocating the buffer, so that we don't have to worry about freeing
2336 * the buffer, and so that we don't try to allocate a buffer bigger
2337 * than the data we'll actually be copying, and thus don't run the risk
2338 * of crashing if the buffer is *so* big that we fail to allocate it
2339 * and "g_new0()" aborts.
2341 tvb_ensure_bytes_exist(tvb, *offset, len);
2344 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2345 * do what we do now, and null-terminate the string (which also means
2346 * we don't need to zero out the entire allocation, just the last byte)?
2348 *seq = g_new0(gchar, len + 1);
2349 tvb_memcpy( tvb, *seq, *offset, len);
2354 /* Copy a 2 octet sequence from the tvbuff
2355 * which represents a signed short value, and convert
2356 * it to a signed short value, taking into account byte order.
2357 * offset is first incremented so that it falls on a proper alignment
2358 * boundary for short values.
2359 * offset is then incremented by 2, to indicate the 2 octets which
2360 * have been processed.
2363 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2367 /* short values must be aligned on a 2 byte boundary */
2368 while( ( (*offset + boundary) % 2) != 0)
2371 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2372 tvb_get_letohs (tvb, *offset);
2380 /* Copy an octet sequence from the tvbuff
2381 * which represents a string, and convert
2382 * it to an string value, taking into account byte order.
2383 * offset is first incremented so that it falls on a proper alignment
2384 * boundary for string values. (begins with an unsigned long LI)
2386 * String sequence is copied to a buffer "seq". This must
2387 * be freed by the calling program.
2388 * offset is then incremented, to indicate the octets which
2389 * have been processed.
2391 * returns number of octets in the sequence
2393 * Note: This function only supports single byte encoding at the
2394 * moment until I get a handle on multibyte encoding etc.
2399 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2404 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2407 (*offset)++; /* must step past \0 delimiter */
2411 get_CDR_octet_seq(tvb, seq, offset, slength);
2413 *seq = g_strdup(""); /* zero-length string */
2416 return slength; /* return length */
2420 /* Process a sequence of octets that represent the
2421 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2423 * This function also increments offset to the correct position.
2425 * It will parse the TypeCode and output data to the "tree" provided
2428 * It returns a guint32 representing a TCKind value.
2431 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2432 gboolean stream_is_big_endian, int boundary,
2433 MessageHeader * header ) {
2436 gint16 s_octet2; /* signed int16 */
2437 guint16 u_octet2; /* unsigned int16 */
2438 guint32 u_octet4; /* unsigned int32 */
2440 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2442 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2443 *offset-sizeof(val),4,val);
2446 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2449 case tk_null: /* empty parameter list */
2451 case tk_void: /* empty parameter list */
2453 case tk_short: /* empty parameter list */
2455 case tk_long: /* empty parameter list */
2457 case tk_ushort: /* empty parameter list */
2459 case tk_ulong: /* empty parameter list */
2461 case tk_float: /* empty parameter list */
2463 case tk_double: /* empty parameter list */
2465 case tk_boolean: /* empty parameter list */
2467 case tk_char: /* empty parameter list */
2469 case tk_octet: /* empty parameter list */
2471 case tk_any: /* empty parameter list */
2473 case tk_TypeCode: /* empty parameter list */
2475 case tk_Principal: /* empty parameter list */
2477 case tk_objref: /* complex parameter list */
2478 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary);
2480 case tk_struct: /* complex parameter list */
2481 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2483 case tk_union: /* complex parameter list */
2484 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2486 case tk_enum: /* complex parameter list */
2487 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary);
2490 case tk_string: /* simple parameter list */
2491 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2493 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2494 *offset-sizeof(u_octet4),4,u_octet4);
2498 case tk_sequence: /* complex parameter list */
2499 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2501 case tk_array: /* complex parameter list */
2502 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2504 case tk_alias: /* complex parameter list */
2505 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2507 case tk_except: /* complex parameter list */
2508 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2510 case tk_longlong: /* empty parameter list */
2512 case tk_ulonglong: /* empty parameter list */
2514 case tk_longdouble: /* empty parameter list */
2516 case tk_wchar: /* empty parameter list */
2518 case tk_wstring: /* simple parameter list */
2519 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2521 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2522 *offset-sizeof(u_octet4),4,u_octet4);
2526 case tk_fixed: /* simple parameter list */
2527 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2529 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2530 *offset-sizeof(u_octet2),2,u_octet2);
2533 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2535 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2536 *offset-sizeof(s_octet2),2,s_octet2);
2540 case tk_value: /* complex parameter list */
2541 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2543 case tk_value_box: /* complex parameter list */
2544 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2546 case tk_native: /* complex parameter list */
2547 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary);
2549 case tk_abstract_interface: /* complex parameter list */
2550 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary );
2553 g_warning("giop: Unknown TCKind %u \n", val);
2562 /* Copy a 4 octet sequence from the tvbuff
2563 * which represents an unsigned long value, and convert
2564 * it to an unsigned long vaule, taking into account byte order.
2565 * offset is first incremented so that it falls on a proper alignment
2566 * boundary for unsigned long values.
2567 * offset is then incremented by 4, to indicate the 4 octets which
2568 * have been processed.
2571 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2575 /* unsigned long values must be aligned on a 4 byte boundary */
2576 while( ( (*offset + boundary) % 4) != 0)
2579 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2580 tvb_get_letohl (tvb, *offset);
2586 /* Copy a 8 octet sequence from the tvbuff
2587 * which represents an unsigned long long value, and convert
2588 * it to an unsigned long long vaule, taking into account byte order.
2589 * offset is first incremented so that it falls on a proper alignment
2590 * boundary for unsigned long long values.
2591 * offset is then incremented by 4, to indicate the 4 octets which
2592 * have been processed.
2595 guint64 get_CDR_ulong_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2599 /* unsigned long long values must be aligned on a 8 byte boundary */
2600 while( ( (*offset + boundary) % 8) != 0)
2603 val = (stream_is_big_endian) ? tvb_get_ntoh64 (tvb, *offset) :
2604 tvb_get_letoh64 (tvb, *offset);
2610 /* Copy a 2 octet sequence from the tvbuff
2611 * which represents an unsigned short value, and convert
2612 * it to an unsigned short value, taking into account byte order.
2613 * offset is first incremented so that it falls on a proper alignment
2614 * boundary for unsigned short values.
2615 * offset is then incremented by 2, to indicate the 2 octets which
2616 * have been processed.
2619 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2623 /* unsigned short values must be aligned on a 2 byte boundary */
2624 while( ( (*offset + boundary) % 2) != 0)
2627 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2628 tvb_get_letohs (tvb, *offset);
2636 /* Copy a wchar from the tvbuff.
2637 * Caller of this function must remember to free the
2638 * array pointed to by seq.
2639 * This function also increments offset according to
2642 * For GIOP 1.1 read 2 octets and return size -2. The
2643 * negation means there is no size element in the packet
2644 * and therefore no size to add to the tree.
2646 * For GIOP 1.2 read size of wchar and the size
2647 * octets. size is returned as a gint8.
2649 * For both GIOP versions the wchar is returned
2650 * as a printable string.
2654 /* NOTE: This is very primitive in that it just reads
2655 * the wchar as a series of octets and returns them
2656 * to the user. No translation is attempted based on
2657 * byte orientation, nor on code set. I.e it only
2658 * really reads past the wchar and sets the offset
2662 /* The "decoding" is done according to CORBA chapter 15.
2663 * Wchar is not supported for GIOP 1.0.
2666 gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2671 /* CORBA chapter 15:
2672 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2673 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2674 * followed by the elements of the octet sequence representing
2675 * the encoded value of the wchar.
2678 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2679 slength = 2; /* set for GIOP 1.1 length in octets */
2681 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2682 slength = get_CDR_octet(tvb,offset);
2685 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2686 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2688 /* now turn octets (wchar) into something that can be printed by the user */
2689 *seq = make_printable_string(raw_wstring, slength);
2691 g_free(raw_wstring);
2694 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2695 if (header->GIOP_version.minor < 2)
2698 return slength; /* return length */
2703 /* Copy a wstring from the tvbuff.
2704 * Caller of this function must remember to free the
2705 * array pointed to by seq.
2706 * This function also increments offset, according to
2707 * wstring length. length is returned as guint32
2710 /* NOTE: This is very primitive in that it just reads
2711 * the wstring as a series of octets and returns them
2712 * to the user. No translation is attempted based on
2713 * byte orientation, nor on code set. I.e it only
2714 * really reads past the wstring and sets the offset
2718 /* The "decoding" is done according to CORBA chapter 15.
2719 * Wstring is not supported for GIOP 1.0.
2723 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2724 int boundary, MessageHeader * header) {
2729 /* CORBA chapter 15:
2730 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2731 * length and string are NUL terminated (length???).
2732 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2736 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2738 /* get length, same for all GIOP versions,
2739 * although for 1.2 CORBA doesnt say, so assume.
2741 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2745 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2746 slength = 5; /* better than core dumping during debug */
2750 if (header->GIOP_version.minor < 2) {
2752 (*offset)++; /* must step past \0 delimiter */
2754 /* assume length is number of characters and not octets, spec not clear */
2755 slength = slength * 2; /* length in octets is 2 * wstring length */
2759 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2761 /* now turn octets (wstring) into something that can be printed by the user */
2762 *seq = make_printable_string(raw_wstring, slength);
2764 g_free(raw_wstring);
2767 return slength; /* return length */
2774 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2776 * typedef short AddressingDisposition;
2777 * const short KeyAddr = 0;
2778 * const short ProfileAddr = 1;
2779 * const short ReferenceAddr = 2;
2780 * struct IORAddressingInfo {
2781 * unsigned long selected_profile_index;
2785 * union TargetAddress switch (AddressingDisposition) {
2786 * case KeyAddr: sequence <octet> object_key;
2787 * case ProfileAddr: IOP::TaggedProfile profile;
2788 * case ReferenceAddr: IORAddressingInfo ior;
2793 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2794 gboolean stream_is_big_endian, guint32 *object_key_len,
2795 gchar **object_key_val)
2797 guint16 discriminant;
2799 gchar *p_object_key;
2804 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2807 proto_tree_add_text (tree, tvb, *offset -2, 2,
2808 "TargetAddress Discriminant: %u", discriminant);
2811 switch (discriminant)
2813 case 0: /* KeyAddr */
2814 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2817 proto_tree_add_text (tree, tvb, *offset -4, 4,
2818 "KeyAddr (object key length): %u", len);
2823 get_CDR_octet_seq(tvb, &object_key, offset, len);
2824 p_object_key = make_printable_string( object_key, len );
2828 proto_tree_add_text (tree, tvb, *offset -len, len,
2829 "KeyAddr (object key): %s", p_object_key);
2831 g_free( p_object_key );
2832 if (object_key_len) {
2833 *object_key_len = len;
2835 if (object_key_val) {
2836 *object_key_val = object_key;
2838 g_free( object_key );
2842 case 1: /* ProfileAddr */
2843 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2844 stream_is_big_endian, NULL);
2846 case 2: /* ReferenceAddr */
2847 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2851 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2852 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2855 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2863 dissect_reply_body (tvbuff_t *tvb, guint offset, packet_info *pinfo,
2864 proto_tree *tree, gboolean stream_is_big_endian,
2865 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2867 guint sequence_length;
2868 gboolean exres = FALSE; /* result of trying explicit dissectors */
2869 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2872 * comp_req_list stuff
2875 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2879 switch (reply_status)
2881 case SYSTEM_EXCEPTION:
2883 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2886 case USER_EXCEPTION:
2888 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2892 proto_tree_add_text(tree, tvb, offset-4, 4,
2893 "Exception length: %u", sequence_length);
2895 if (sequence_length != 0 && sequence_length < ITEM_LABEL_LENGTH)
2899 tvb_ensure_bytes_exist(tvb, offset, sequence_length);
2900 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2902 /* read exception id from buffer and store in*/
2904 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2908 proto_tree_add_string(tree, hf_giop_exception_id, tvb,
2909 offset, sequence_length, header->exception_id);
2915 offset += sequence_length;
2921 * Now just fall through to the NO_EXCEPTION part
2922 * as this is common .
2930 /* lookup MFN in hash directly */
2932 mfn = get_mfn_from_fn(pinfo->fd->num);
2934 if (mfn == pinfo->fd->num)
2935 return; /* no matching frame number, what am I */
2937 /* get entry for this MFN */
2938 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2941 return; /* no matching entry */
2945 * If this packet is a REPLY to a RESOLVE(request)
2947 * TODO - make this lookup faster -- FS
2950 if (!strcmp(giop_op_resolve,entry->operation)) {
2951 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2955 /* TODO -- Put stuff here for other "interesting operations" */
2959 * Call sub dissector.
2960 * First try an find a explicit sub_dissector, then if that
2961 * fails, try the heuristic method.
2966 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
2969 /* Only call heuristic if no explicit dissector was found */
2972 exres = try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
2975 if (!exres && !strcmp(giop_op_is_a, entry->operation) && tree) {
2976 proto_tree_add_text(tree, tvb, offset - 1, 1, "Type Id%s matched",
2977 get_CDR_boolean(tvb, &offset) ? "" : " not");
2981 gint stub_length = tvb_reported_length_remaining(tvb, offset);
2983 proto_tree_add_text(tree, tvb, offset, -1,
2984 "Stub data (%d byte%s)", stub_length,
2985 plurality(stub_length, "", "s"));
2990 case LOCATION_FORWARD:
2991 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2995 case LOCATION_FORWARD_PERM:
2996 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3000 case NEEDS_ADDRESSING_MODE: {
3002 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3004 proto_tree_add_text (tree, tvb, offset -2, 2,
3005 "AddressingDisposition: %u", addr_disp);
3013 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
3019 g_free(repoid); /* free resource */
3029 /* The format of the Reply Header for GIOP 1.0 and 1.1
3030 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
3032 struct ReplyHeader_1_0 {
3033 IOP::ServiceContextList service_context;
3034 unsigned long request_id;
3035 ReplyStatusType_1_0 reply_status;
3039 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3040 MessageHeader * header,
3041 gboolean stream_is_big_endian) {
3045 guint32 reply_status;
3046 proto_tree *reply_tree = NULL;
3048 guint32 mfn; /* matching frame number */
3051 tf = proto_tree_add_text (tree, tvb, offset, -1,
3052 "General Inter-ORB Protocol Reply");
3053 if (reply_tree == NULL)
3055 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3061 * Decode IOP::ServiceContextList
3064 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3066 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3068 if (check_col(pinfo->cinfo, COL_INFO)) {
3069 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id );
3073 proto_tree_add_uint(reply_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
3076 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3078 if (check_col(pinfo->cinfo, COL_INFO)) {
3079 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3080 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3085 proto_tree_add_uint(reply_tree, hf_giop_reply_status, tvb,
3086 offset-4, 4, reply_status);
3091 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3094 if (! pinfo->fd->flags.visited) {
3095 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3096 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3097 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3101 header->req_id = request_id; /* save for sub dissector */
3102 header->rep_status = reply_status; /* save for sub dissector */
3104 /* Do we have a body */
3105 if (tvb_reported_length_remaining(tvb, offset))
3106 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3107 reply_status, header,tree);
3112 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3113 * and 1.1 header, only the fields have been rearranged. From Section
3114 * 15.4.3.1 of the CORBA 2.4 specification:
3116 * struct ReplyHeader_1_2 {
3117 * unsigned long request_id;
3118 * ReplyStatusType_1_2 reply_status;
3119 * IOP:ServiceContextList service_context;
3123 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3125 MessageHeader * header,
3126 gboolean stream_is_big_endian) {
3130 guint32 reply_status;
3131 proto_tree *reply_tree = NULL;
3133 guint32 mfn; /* matching frame number */
3136 tf = proto_tree_add_text (tree, tvb, offset, -1,
3137 "General Inter-ORB Protocol Reply");
3138 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3141 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3143 if (check_col(pinfo->cinfo, COL_INFO)) {
3144 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
3148 proto_tree_add_uint (reply_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
3151 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3153 if (check_col(pinfo->cinfo, COL_INFO)) {
3154 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3155 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3160 proto_tree_add_uint(reply_tree, hf_giop_reply_status, tvb,
3161 offset-4, 4, reply_status);
3165 * Decode IOP::ServiceContextList
3168 decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3171 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3174 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3177 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3180 if (! pinfo->fd->flags.visited) {
3181 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3182 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3183 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3188 * Add header to argument list so sub dissector can get header info.
3191 header->req_id = request_id; /* save for sub dissector */
3192 header->rep_status = reply_status; /* save for sub dissector */
3194 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3195 reply_status,header,tree);
3201 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3203 gboolean stream_is_big_endian) {
3207 proto_tree *cancel_request_tree = NULL;
3211 tf = proto_tree_add_text (tree, tvb, offset, -1,
3212 "General Inter-ORB Protocol CancelRequest");
3213 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3216 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3218 if (check_col(pinfo->cinfo, COL_INFO)) {
3219 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
3223 proto_tree_add_uint (cancel_request_tree,hf_giop_req_id, tvb, offset-4, 4, request_id);
3229 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3230 * in section 15.4.2.1 of the CORBA 2.4 specification.
3232 * struct RequestHeader{
3233 * IOP::ServiceContextList service_context;
3234 * unsigned long request_id;
3235 * boolean response_expected;
3236 * octet reserved[3]; // Only in GIOP 1.1
3237 * sequence<octet> object_key;
3239 * CORBA::OctetSeq requesting_principal;
3243 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3245 MessageHeader * header, gboolean stream_is_big_endian)
3251 guint32 objkey_len = 0; /* object key length */
3252 gchar *objkey = NULL; /* object key sequence */
3253 gboolean exres = FALSE; /* result of trying explicit dissectors */
3256 gchar *requesting_principal;
3257 gchar *print_requesting_principal;
3258 guint8 response_expected;
3260 proto_tree *request_tree = NULL;
3263 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3268 tf = proto_tree_add_text (tree, tvb, offset, -1,
3269 "General Inter-ORB Protocol Request");
3270 if (request_tree == NULL)
3272 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3280 * Decode IOP::ServiceContextList
3283 decode_ServiceContextList(tvb, request_tree, &offset,stream_is_big_endian, 0);
3286 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3287 if (check_col(pinfo->cinfo, COL_INFO))
3289 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
3293 proto_tree_add_uint (request_tree,hf_giop_req_id, tvb, offset-4, 4, request_id);
3296 response_expected = tvb_get_guint8( tvb, offset );
3298 if (check_col(pinfo->cinfo, COL_INFO))
3300 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3301 response_expected ? "two-way" : "one-way");
3305 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3306 "Response expected: %u", response_expected);
3309 if( header->GIOP_version.minor > 0)
3311 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3314 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3315 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3322 /* Length of object_key sequence */
3323 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3328 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3329 /**/ "Object Key length: %u", objkey_len);
3334 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3338 proto_tree_add_item(request_tree, hf_giop_objekt_key, tvb, offset - objkey_len, objkey_len, FALSE);
3345 * Register a cleanup function in case on of our tvbuff accesses
3346 * throws an exception. We need to clean up objkey.
3348 CLEANUP_PUSH(g_free, objkey);
3350 /* length of operation string and string */
3351 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3354 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3355 /**/ "Operation length: %u", len);
3360 if (check_col(pinfo->cinfo, COL_INFO))
3362 col_append_fstr(pinfo->cinfo, COL_INFO, ": op=%s", operation);
3366 proto_tree_add_string (request_tree, hf_giop_req_operation,tvb, offset - len, len, operation);
3372 * Register a cleanup function in case on of our tvbuff accesses
3373 * throws an exception. We need to clean up operation.
3375 CLEANUP_PUSH(g_free, operation);
3377 /* length of requesting_principal string */
3378 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3381 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3382 /**/ "Requesting Principal Length: %u", len);
3387 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3389 print_requesting_principal = make_printable_string(requesting_principal, len);
3393 proto_tree_add_text (request_tree, tvb, offset - len, len,
3394 /**/ "Requesting Principal: %s", print_requesting_principal);
3398 g_free( print_requesting_principal );
3399 g_free( requesting_principal );
3404 * Save FN,reqid,and operation for later. Add sub_handle later.
3405 * But only if user is NOT clicking.
3408 if (! pinfo->fd->flags.visited)
3409 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3410 request_id,operation,NULL);
3414 * Call subdissector here before freeing "operation" and "key"
3415 * pass request_id also.
3416 * First try an find an explicit sub_dissector, then if that
3417 * fails, try the heuristic method.
3422 header->req_id = request_id; /* save for sub dissector */
3423 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3427 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3430 /* Only call heuristic if no explicit dissector was found */
3433 exres = try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3436 if (!exres && !strcmp(giop_op_is_a, operation) && request_tree) {
3438 len = get_CDR_string(tvb, &type_id, &offset, stream_is_big_endian, 0);
3439 proto_tree_add_text(request_tree, tvb, offset - len - 4, 4,
3440 "Type Id length: %d", len);
3441 proto_tree_add_text(request_tree, tvb, offset - len, len,
3442 "Type Id: %s", type_id);
3446 gint stub_length = tvb_reported_length_remaining(tvb, offset);
3448 proto_tree_add_text(request_tree, tvb, offset, -1,
3449 "Stub data (%d byte%s)", stub_length,
3450 plurality(stub_length, "", "s"));
3454 * We're done with operation, so we can call the cleanup handler to free
3455 * it, and then pop the cleanup handler.
3457 CLEANUP_CALL_AND_POP;
3460 * We're done with objkey, so we can call the cleanup handler to free
3461 * it, and then pop the cleanup handler.
3463 CLEANUP_CALL_AND_POP;
3467 /** The format of a GIOP 1.2 RequestHeader message is
3468 * (CORBA 2.4, sec. 15.4.2):
3470 * struct RequestHeader_1_2 {
3471 * unsigned long request_id;
3472 * octet response_flags;
3473 * octet reserved[3];
3474 * TargetAddress target;
3476 * IOP::ServiceContextList service_context;
3477 * // requesting_principal not in GIOP 1.2
3481 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3483 MessageHeader * header, gboolean stream_is_big_endian)
3488 guint8 response_flags;
3490 gchar *operation = NULL;
3491 proto_tree *request_tree = NULL;
3493 gboolean exres = FALSE; /* result of trying explicit dissectors */
3495 guint32 objkey_len = 0; /* object key length */
3496 gchar *objkey = NULL; /* object key sequence */
3497 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3501 tf = proto_tree_add_text (tree, tvb, offset, -1,
3502 "General Inter-ORB Protocol Request");
3503 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3506 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3507 if (check_col(pinfo->cinfo, COL_INFO))
3509 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
3513 proto_tree_add_uint (request_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
3516 response_flags = tvb_get_guint8( tvb, offset );
3520 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3521 "Response flags: %s (%u)",
3522 val_to_str(response_flags, sync_scope, "(0x%x)"),
3526 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3529 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3530 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3534 dissect_target_address(tvb, pinfo, &offset, request_tree, stream_is_big_endian,
3535 &objkey_len, &objkey);
3537 repoid = get_repoid_from_objkey(giop_objkey_hash, objkey, objkey_len);
3541 /* length of operation string */
3542 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3545 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3546 /**/ "Operation length: %u", len);
3551 if (check_col(pinfo->cinfo, COL_INFO))
3553 col_append_fstr(pinfo->cinfo, COL_INFO, ": op=%s", operation);
3557 proto_tree_add_string (request_tree,hf_giop_req_operation, tvb, offset - len, len, operation);
3564 * Register a cleanup function in case on of our tvbuff accesses
3565 * throws an exception. We need to clean up operation.
3567 CLEANUP_PUSH(g_free, operation);
3570 * Decode IOP::ServiceContextList
3573 decode_ServiceContextList(tvb, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3576 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3577 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3578 * GIOP octet stream start.
3581 if (tvb_reported_length_remaining(tvb, offset) > 0)
3583 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3587 * Save FN,reqid,and operation for later. Add sub_handle later.
3588 * But only if user is NOT clicking.
3591 if (! pinfo->fd->flags.visited)
3592 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3593 request_id,operation,NULL);
3597 * Call sub dissector.
3598 * First try an find a explicit sub_dissector, then if that
3599 * fails, try the heuristic method.
3603 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3606 /* Only call heuristic if no explicit dissector was found */
3609 exres = try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3612 if (!exres && !strcmp(giop_op_is_a, operation) && request_tree) {
3614 len = get_CDR_string(tvb, &type_id, &offset, stream_is_big_endian, 0);
3615 proto_tree_add_text(request_tree, tvb, offset - len - 4, 4,
3616 "Type Id length: %d", len);
3617 proto_tree_add_text(request_tree, tvb, offset - len, len,
3618 "Type Id: %s", type_id);
3622 gint stub_length = tvb_reported_length_remaining(tvb, offset);
3624 proto_tree_add_text(request_tree, tvb, offset, -1,
3625 "Stub data (%d byte%s)", stub_length,
3626 plurality(stub_length, "", "s"));
3630 * We're done with operation, so we can call the cleanup handler to free
3631 * it, and then pop the cleanup handler.
3633 CLEANUP_CALL_AND_POP;
3637 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3638 proto_tree * tree, MessageHeader * header,
3639 gboolean stream_is_big_endian)
3644 proto_tree *locate_request_tree = NULL;
3649 tf = proto_tree_add_text (tree, tvb, offset, -1,
3650 "General Inter-ORB Locate Request");
3651 if (locate_request_tree == NULL)
3653 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3658 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3659 if (check_col(pinfo->cinfo, COL_INFO))
3661 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u op=LocateRequest", request_id);
3663 if (locate_request_tree)
3665 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3666 "Request id: %u", request_id);
3669 if(header->GIOP_version.minor < 2)
3671 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3672 if (locate_request_tree)
3674 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3675 "Object Key length: %u", len);
3680 if(locate_request_tree)
3683 proto_tree_add_item(locate_request_tree, hf_giop_objekt_key, tvb, offset-len, len, FALSE);
3688 else /* GIOP 1.2 and higher */
3690 dissect_target_address(tvb, pinfo, &offset, locate_request_tree,
3691 stream_is_big_endian, NULL, NULL);
3696 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3697 proto_tree * tree, MessageHeader * header,
3698 gboolean stream_is_big_endian)
3702 guint32 locate_status;
3705 proto_tree *locate_reply_tree = NULL;
3710 tf = proto_tree_add_text (tree, tvb, offset, -1,
3711 "General Inter-ORB Locate Reply");
3712 if (locate_reply_tree == NULL)
3714 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3719 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3720 if (check_col(pinfo->cinfo, COL_INFO))
3722 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
3724 if (locate_reply_tree)
3726 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3727 "Request id: %u", request_id);
3730 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3731 if (locate_reply_tree)
3733 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3734 "Locate status: %s",
3735 val_to_str(locate_status, giop_locate_status_types, "(0x%x)")
3739 /* Decode the LocateReply body.
3741 * For GIOP 1.0 and 1.1 body immediately follows header.
3742 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3746 if (header->GIOP_version.minor > 1) {
3747 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3751 switch(locate_status) {
3752 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3753 case OBJECT_FORWARD_PERM:
3754 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3756 case LOC_SYSTEM_EXCEPTION:
3757 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3759 case LOC_NEEDS_ADDRESSING_MODE:
3760 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3761 if(locate_reply_tree) {
3762 proto_tree_add_text (tree, tvb, offset -2, 2,
3763 "AddressingDisposition: %u", addr_disp);
3766 default: /* others have no reply body */
3773 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3774 gboolean stream_is_big_endian)
3778 proto_tree *fragment_tree = NULL;
3783 tf = proto_tree_add_text (tree, tvb, offset, -1,
3784 "General Inter-ORB Fragment");
3785 if (fragment_tree == NULL)
3787 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3792 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3793 if (check_col(pinfo->cinfo, COL_INFO))
3795 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
3799 proto_tree_add_uint (fragment_tree, hf_giop_req_id, tvb, offset-4, 4,request_id);
3805 /* Main entry point */
3807 static void dissect_giop_common (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3809 MessageHeader header;
3810 tvbuff_t *giop_header_tvb;
3811 tvbuff_t *payload_tvb;
3813 proto_tree *clnp_tree = NULL;
3816 guint minor_version;
3817 gboolean stream_is_big_endian;
3818 const char *gMessageType;
3824 giop_dump_collection(cd_module_hash);
3825 giop_dump_collection(cd_objkey_hash);
3826 giop_dump_collection(cd_heuristic_users);
3827 giop_dump_collection(cd_complete_reply_hash);
3828 giop_dump_collection(cd_complete_request_list);
3831 header.exception_id = NULL;
3833 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3834 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3837 * because I have added extra elements in MessageHeader struct
3838 * for sub dissectors. -- FS
3841 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3844 if (check_col (pinfo->cinfo, COL_PROTOCOL))
3846 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3849 if (header.GIOP_version.major != GIOP_MAJOR ||
3850 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3852 /* Bad version number; should we note that and dissect the rest
3853 as data, or should this be done outside dissect_giop_common()
3854 (which is called as the PDU dissector for GIOP-over-TCP,
3855 so it can't return anything), with the test returning FALSE
3856 on the theory that it might have been some other packet that
3857 happened to begin with "GIOP"? We do the former, for now.
3858 If we should return FALSE, we should do so *without* setting
3859 the "Info" column, *without* setting the "Protocol" column,
3860 and *without* adding anything to the protocol tree. */
3862 if (check_col (pinfo->cinfo, COL_INFO))
3864 col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3865 header.GIOP_version.major, header.GIOP_version.minor);
3869 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3870 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3871 proto_tree_add_text (clnp_tree, giop_header_tvb, 0, -1,
3872 "Version %u.%u not supported",
3873 header.GIOP_version.major,
3874 header.GIOP_version.minor);
3876 call_dissector(data_handle,payload_tvb, pinfo, tree);
3880 if (check_col (pinfo->cinfo, COL_INFO))
3882 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3883 header.GIOP_version.major, header.GIOP_version.minor,
3884 val_to_str(header.message_type, giop_message_types,
3885 "Unknown message type (0x%02x)"));
3888 stream_is_big_endian = is_big_endian (&header);
3890 if (stream_is_big_endian)
3891 message_size = pntohl (&header.message_size);
3893 message_size = pletohl (&header.message_size);
3895 if (check_col (pinfo->cinfo, COL_INFO))
3897 gMessageType = val_to_str(header.message_type, giop_message_types, "Unknown message type (0x%02x)");
3898 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s s=%u",
3899 header.GIOP_version.major, header.GIOP_version.minor, gMessageType, message_size );
3904 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3905 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3906 proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3907 "Magic number: %s", GIOP_MAGIC);
3908 proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3910 header.GIOP_version.major,
3911 header.GIOP_version.minor);
3912 switch (minor_version)
3916 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3917 "Flags: 0x%02x (%s%s%s%s)",
3919 ,(stream_is_big_endian) ? "big-endian" : "little-endian"
3920 ,(header.flags & 0x02) ? ", fragment" : ""
3921 ,(header.flags & 0x04) ? ", ZIOP supported" : ""
3922 ,(header.flags & 0x08) ? ", ZIOP enabled" : ""
3926 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3927 "Byte ordering: %s-endian",
3928 (stream_is_big_endian) ? "big" : "little");
3932 } /* minor_version */
3934 gMessageType = val_to_str(header.message_type, giop_message_types, "(0x%02x)" );
3936 proto_tree_add_uint_format (clnp_tree,
3937 hf_giop_message_type,
3938 giop_header_tvb, 7, 1,
3939 header.message_type,
3940 "Message type: %s", gMessageType );
3942 proto_tree_add_uint (clnp_tree,
3943 hf_giop_message_size,
3944 giop_header_tvb, 8, 4, message_size);
3949 if (check_col (pinfo->cinfo, COL_INFO))
3951 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3952 header.GIOP_version.major, header.GIOP_version.minor,
3953 val_to_str(header.message_type, giop_message_types, "(0x%x)"));
3957 if (header.flags & 0x08)
3959 payload_tvb = tvb_uncompress( tvb, GIOP_HEADER_SIZE, tvb_length_remaining(tvb, GIOP_HEADER_SIZE ) );
3960 tvb_set_child_real_data_tvbuff( tvb, payload_tvb );
3961 add_new_data_source (pinfo, payload_tvb, "decompressed Content");
3964 switch (header.message_type)
3968 if(header.GIOP_version.minor < 2)
3970 dissect_giop_request_1_1 (payload_tvb, pinfo, tree,
3971 &header, stream_is_big_endian);
3975 dissect_giop_request_1_2 (payload_tvb, pinfo, tree,
3976 &header, stream_is_big_endian);
3983 if(header.GIOP_version.minor < 2)
3985 dissect_giop_reply (payload_tvb, pinfo, tree, &header,
3986 stream_is_big_endian);
3990 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree,
3991 &header, stream_is_big_endian);
3995 dissect_giop_cancel_request(payload_tvb, pinfo, tree,
3996 stream_is_big_endian);
3999 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
4000 stream_is_big_endian);
4003 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
4004 stream_is_big_endian);
4007 dissect_giop_fragment(payload_tvb, pinfo, tree,
4008 stream_is_big_endian);
4013 } /* switch message_type */
4017 * XXX - we should catch exceptions here, so that we can free
4018 * this if an exception is thrown.
4019 * We'd then have to forward the exception.
4021 if (header.exception_id != NULL)
4022 g_free(header.exception_id);
4026 get_giop_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
4029 MessageHeader header;
4031 gboolean stream_is_big_endian;
4033 if ( tvb_memeql(tvb, 0, GIOP_MAGIC ,4) != 0)
4036 tvb_memcpy (tvb, (guint8 *)&header, offset, GIOP_HEADER_SIZE );
4038 stream_is_big_endian = is_big_endian (&header);
4040 if (stream_is_big_endian)
4041 message_size = pntohl (&header.message_size);
4043 message_size = pletohl (&header.message_size);
4046 return message_size + GIOP_HEADER_SIZE;
4050 dissect_giop_tcp (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
4051 tcp_dissect_pdus(tvb, pinfo, tree, giop_desegment, GIOP_HEADER_SIZE,
4052 get_giop_pdu_len, dissect_giop_common);
4056 dissect_giop_heur (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
4060 conversation_t *conversation;
4061 /* check magic number and version */
4064 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
4066 tot_len = tvb_length(tvb);
4068 if (tot_len < GIOP_HEADER_SIZE) /* tot_len < 12 */
4070 /* Not enough data captured to hold the GIOP header; don't try
4071 to interpret it as GIOP. */
4074 if ( tvb_memeql(tvb, 0, GIOP_MAGIC ,4) != 0)
4077 if ( pinfo->ptype == PT_TCP )
4080 * Make the GIOP dissector the dissector for this conversation.
4082 * If this isn't the first time this packet has been processed,
4083 * we've already done this work, so we don't need to do it
4086 if (!pinfo->fd->flags.visited)
4088 conversation = find_conversation(pinfo->fd->num, &pinfo->src,
4089 &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4090 if (conversation == NULL)
4092 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
4093 &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4096 conversation_set_dissector(conversation, giop_tcp_handle);
4098 dissect_giop_tcp (tvb, pinfo, tree);
4102 dissect_giop_common (tvb, pinfo, tree);
4110 proto_register_giop (void)
4112 static hf_register_info hf[] = {
4113 { &hf_giop_message_type,
4114 { "Message type", "giop.type",
4115 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4118 { &hf_giop_message_size,
4119 { "Message size", "giop.len",
4120 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4124 { "Repository ID", "giop.repoid",
4125 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4128 { &hf_giop_string_length,
4129 { "String Length", "giop.strlen",
4130 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4133 { &hf_giop_sequence_length,
4134 { "Sequence Length", "giop.seqlen",
4135 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4138 { &hf_giop_profile_id,
4139 { "Profile ID", "giop.profid",
4140 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
4145 { "IOR::type_id", "giop.typeid",
4146 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4149 { &hf_giop_iiop_v_maj,
4150 { "IIOP Major Version", "giop.iiop_vmaj",
4151 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4154 { &hf_giop_iiop_v_min,
4155 { "IIOP Minor Version", "giop.iiop_vmin",
4156 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4159 { &hf_giop_compressed,
4160 { "ZIOP", "giop.compressed",
4161 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4164 { &hf_giop_endianess,
4165 { "Endianess", "giop.endianess",
4166 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4169 { &hf_giop_IIOP_tag,
4170 { "IIOP Component TAG", "giop.iioptag",
4171 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4175 { "IOR Profile TAG", "giop.iortag",
4176 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4180 { "TypeCode enum", "giop.TCKind",
4181 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4184 { &hf_giop_typecode_count,
4185 { "TypeCode count", "giop.tccount",
4186 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4189 { &hf_giop_typecode_default_used,
4190 { "default_used", "giop.tcdefault_used",
4191 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4194 { &hf_giop_typecode_digits,
4195 { "Digits", "giop.tcdigits",
4196 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4200 { &hf_giop_typecode_length,
4201 { "Length", "giop.tclength",
4202 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4205 { &hf_giop_typecode_max_length,
4206 { "Maximum length", "giop.tcmaxlen",
4207 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4210 { &hf_giop_typecode_member_name,
4211 { "TypeCode member name", "giop.tcmemname",
4212 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4215 { &hf_giop_typecode_name,
4216 { "TypeCode name", "giop.tcname",
4217 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4220 { &hf_giop_typecode_scale,
4221 { "Scale", "giop.tcscale",
4222 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4225 { &hf_giop_typecode_ValueModifier,
4226 { "ValueModifier", "giop.tcValueModifier",
4227 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4230 { &hf_giop_typecode_Visibility,
4231 { "Visibility", "giop.tcVisibility",
4232 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4237 { &hf_giop_type_boolean,
4238 { "TypeCode boolean data", "giop.tcboolean",
4239 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4242 { &hf_giop_type_char,
4243 { "TypeCode char data", "giop.tcchar",
4244 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4247 { &hf_giop_type_double,
4248 { "TypeCode double data", "giop.tcdouble",
4249 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4252 { &hf_giop_type_enum,
4253 { "TypeCode enum data", "giop.tcenumdata",
4254 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4258 * float as double ?? -- FIX
4261 { &hf_giop_type_float,
4262 { "TypeCode float data", "giop.tcfloat",
4263 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4266 { &hf_giop_type_long,
4267 { "TypeCode long data", "giop.tclongdata",
4268 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4271 { &hf_giop_type_octet,
4272 { "TypeCode octet data", "giop.tcoctet",
4273 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4276 { &hf_giop_type_short,
4277 { "TypeCode short data", "giop.tcshortdata",
4278 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4281 { &hf_giop_type_string,
4282 { "TypeCode string data", "giop.tcstring",
4283 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4286 { &hf_giop_type_ulong,
4287 { "TypeCode ulong data", "giop.tculongdata",
4288 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4291 { &hf_giop_type_ushort,
4292 { "TypeCode ushort data", "giop.tcushortdata",
4293 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4297 * IIOP Module - Chapter 15.10.2
4300 { &hf_giop_iiop_host,
4301 { "IIOP::Profile_host", "giop.iiop.host",
4302 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4306 { &hf_giop_iiop_port,
4307 { "IIOP::Profile_port", "giop.iiop.port",
4308 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4313 * IIOP ServiceContext
4316 { &hf_giop_iop_vscid,
4317 { "VSCID", "giop.iiop.vscid",
4318 FT_UINT32, BASE_HEX, NULL, 0xffffff00, "", HFILL }
4322 { &hf_giop_iop_scid,
4323 { "SCID", "giop.iiop.scid",
4324 FT_UINT32, BASE_HEX, NULL, 0x000000ff, "", HFILL }
4329 { "Request id", "giop.request_id",
4330 FT_UINT32, BASE_DEC, NULL, 0, "", HFILL }
4333 { &hf_giop_req_operation,
4334 { "Request operation", "giop.request_op",
4335 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4337 { &hf_giop_reply_status,
4338 { "Reply status", "giop.replystatus",
4339 FT_UINT32, BASE_DEC, VALS(reply_status_types), 0x0, "", HFILL }
4341 { &hf_giop_exception_id,
4342 { "Exception id", "giop.exceptionid",
4343 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4345 { &hf_giop_objekt_key,
4346 { "Object Key", "giop.objektkey",
4347 FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
4354 static gint *ett[] = {
4358 &ett_giop_cancel_request,
4359 &ett_giop_locate_request,
4360 &ett_giop_locate_reply,
4367 module_t *giop_module;
4369 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4371 proto_register_field_array (proto_giop, hf, array_length (hf));
4372 proto_register_subtree_array (ett, array_length (ett));
4375 /* register init routine */
4377 register_init_routine( &giop_init); /* any init stuff */
4379 /* register preferences */
4380 giop_module = prefs_register_protocol(proto_giop, NULL);
4381 prefs_register_bool_preference(giop_module, "desegment_giop_messages",
4382 "Reassemble GIOP messages spanning multiple TCP segments",
4383 "Whether the GIOP dissector should reassemble messages spanning multiple TCP segments."
4384 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4386 prefs_register_string_preference(giop_module, "ior_txt", "Stringified IORs",
4387 "File containing stringified IORs, one per line.", &giop_ior_file);
4390 * Init the giop user module hash tables here, as giop users
4391 * will populate it via register_giop_user_module BEFORE my
4392 * own giop_init() is called.
4395 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4401 void proto_reg_handoff_giop (void) {
4402 data_handle = find_dissector("data");
4403 giop_tcp_handle = create_dissector_handle(dissect_giop_tcp, proto_giop);
4404 heur_dissector_add("tcp", dissect_giop_heur, proto_giop);
4405 /* Support DIOP (GIOP/UDP) */
4406 heur_dissector_add("udp", dissect_giop_heur, proto_giop);
4407 /* Port will be set by conversation */
4408 dissector_add("tcp.port", 0, giop_tcp_handle);
4417 * Ref Corba v2.4.2 Chapter 13
4425 typedef unsigned long ProfileId;
4427 const ProfileId TAG_INTERNET_IOP = 0;
4428 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4430 struct TaggedProfile {
4432 sequence <octet> profile_data;
4437 sequence <TaggedProfile> profiles;
4440 typedef unsigned long ComponentId;
4442 struct TaggedComponent {
4444 sequence <octet> component_data;
4447 typedef sequence <TaggedComponent> MultipleComponentProfile;
4453 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4454 guint32 boundary, gboolean stream_is_big_endian) {
4457 guint32 seqlen_p; /* sequence length of profiles */
4460 proto_tree *tree = NULL; /* IOR tree */
4463 gchar *repobuf; /* for repository ID */
4467 /* create a subtree */
4470 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
4471 tree = proto_item_add_subtree (tf, ett_giop_ior);
4475 /* Get type_id == Repository ID */
4477 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4480 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4481 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4483 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4484 *offset-u_octet4,u_octet4,repobuf);
4489 * Register a cleanup function in case on of our tvbuff accesses
4490 * throws an exception. We need to clean up repobuf.
4491 * We can't free it yet, as we must wait until we have the object
4492 * key, as we have to add both to the hash table.
4494 CLEANUP_PUSH(g_free, repobuf);
4496 /* Now get a sequence of profiles */
4497 /* Get sequence length (number of elements) */
4499 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4501 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4502 *offset-sizeof(seqlen_p),4,seqlen_p);
4506 /* fetch all TaggedProfiles in this sequence */
4508 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4509 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4513 * We're done with repobuf, so we can call the cleanup handler to free
4514 * it, and then pop the cleanup handler.
4516 CLEANUP_CALL_AND_POP;
4520 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4521 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4523 guint32 seqlen_pd; /* sequence length of profile data */
4525 guint32 pidtag; /* profile ID TAG */
4527 gchar *profile_data; /* profile_data pointer */
4528 gchar *p_profile_data; /* printable profile_data pointer */
4530 guint32 new_boundary; /* for encapsulations encountered */
4531 gboolean new_big_endianess; /* for encapsulations encountered */
4533 /* Get ProfileId tag */
4535 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4538 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4539 *offset-sizeof(pidtag),4,pidtag);
4542 /* get sequence length, new endianness and boundary for encapsulation */
4544 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4545 stream_is_big_endian, boundary,
4546 &new_big_endianess, &new_boundary);
4548 /* return if zero length sequence */
4555 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4556 * decode it, otherwise just dump the octet sequence
4558 * also, store IOR in our objectkey hash
4560 * TODO - handle other TAGS
4564 case IOP_TAG_INTERNET_IOP:
4566 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4571 /* fetch all octets in this sequence , but skip endianess */
4573 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4575 /* Make a printable string */
4577 p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4580 proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4581 "Profile Data: %s", p_profile_data);
4584 g_free(p_profile_data);
4586 g_free(profile_data);
4597 * Decode IIOP IOR Profile
4598 * Ref Chap 15.7.2 in Corba Spec
4602 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4603 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4604 gboolean store_flag) {
4606 guint32 i; /* loop index */
4608 guint8 v_major,v_minor; /* IIOP version */
4610 guint32 u_octet4; /* u long */
4611 guint16 u_octet2; /* u short */
4612 guint32 seqlen; /* generic sequence length */
4613 guint32 seqlen1; /* generic sequence length */
4614 gchar *objkey; /* object key pointer */
4615 gchar *p_chars; /* printable characters pointer */
4618 /* Get major/minor version */
4620 v_major = get_CDR_octet(tvb,offset);
4621 v_minor = get_CDR_octet(tvb,offset);
4625 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4626 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4627 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4628 *offset-sizeof(v_minor),1,v_minor );
4634 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4637 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4638 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4640 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4641 *offset-u_octet4,u_octet4,buf);
4645 g_free(buf); /* dont forget */
4649 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4652 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4653 *offset-sizeof(u_octet2),2,u_octet2);
4657 /* Object Key - sequence<octet> object_key */
4659 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4662 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4663 *offset-sizeof(seqlen),4,seqlen);
4667 /* fetch all octets in this sequence */
4668 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4671 * Now we may have the Repository ID from earlier, as well
4672 * as the object key sequence and lengh. So lets store them in
4673 * our objectkey hash and free buffers.
4675 * But only insert if user is not clicking and repo id not NULL.
4681 if(!pinfo->fd->flags.visited)
4682 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4687 * No pinfo, but store anyway if flag set. eg: IOR read from file
4691 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4696 proto_tree_add_item(tree, hf_giop_objekt_key, tvb, *offset -seqlen, seqlen, FALSE);
4702 * Now see if if its v1.1 or 1.2, as they can contain
4703 * extra sequence of IOP::TaggedComponents
4716 /* sequence of IOP::TaggedComponents */
4717 /* Ref Chap 13 in Corba Spec */
4719 /* get sequence length */
4720 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4723 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4724 *offset-sizeof(seqlen),4,seqlen);
4727 for (i=0; i< seqlen; i++) {
4729 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4731 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4732 *offset-sizeof(u_octet4),4,u_octet4);
4735 /* get component_data */
4736 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4738 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4739 *offset-sizeof(seqlen1),4,seqlen1);
4743 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4746 /* Make a printable string of data */
4748 p_chars = make_printable_string(buf, seqlen1);
4750 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4751 "component_data: %s", p_chars);
4765 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4772 * From Section 13.10.2.5 of the CORBA 3.0 spec.
4774 * module CONV_FRAME {
4775 * typedef unsigned long CodeSetId;
4776 * struct CodeSetContext {
4777 * CodeSetId char_data;
4778 * CodeSetId wchar_data;
4782 * Code sets are identified by a 32-bit integer id from OSF.
4783 * See: ftp://ftp.opengroup.org/pub/code_set_registry
4785 static const value_string giop_code_set_vals[] = {
4786 { 0x00010001, "ISO_8859_1" },
4787 { 0x00010002, "ISO_8859_2" },
4788 { 0x00010003, "ISO_8859_3" },
4789 { 0x00010004, "ISO_8859_4" },
4790 { 0x00010005, "ISO_8859_5" },
4791 { 0x00010006, "ISO_8859_6" },
4792 { 0x00010007, "ISO_8859_7" },
4793 { 0x00010008, "ISO_8859_8" },
4794 { 0x00010009, "ISO_8859_9" },
4795 { 0x0001000A, "ISO_8859_10" },
4796 { 0x0001000F, "ISO_8859_15" },
4797 { 0x00010020, "ISO_646" },
4798 { 0x00010100, "ISO_UCS_2_LEVEL_1" },
4799 { 0x00010101, "ISO_UCS_2_LEVEL_2" },
4800 { 0x00010102, "ISO_UCS_2_LEVEL_3" },
4801 { 0x00010104, "ISO_UCS_4_LEVEL_1" },
4802 { 0x00010105, "ISO_UCS_4_LEVEL_2" },
4803 { 0x00010106, "ISO_UCS_4_LEVEL_3" },
4804 { 0x00010108, "ISO_UTF_8" },
4805 { 0x00010109, "ISO_UTF_16" },
4806 { 0x00030001, "JIS_X0201" },
4807 { 0x00030004, "JIS_X0208_1978" },
4808 { 0x00030005, "JIS_X0208_1983" },
4809 { 0x00030006, "JIS_X0208_1990" },
4810 { 0x0003000A, "JIS_X0212" },
4811 { 0x00030010, "JIS_EUCJP" },
4812 { 0x00040001, "KS_C5601" },
4813 { 0x00040002, "KS_C5657" },
4814 { 0x0004000A, "KS_EUCKR" },
4815 { 0x00050001, "CNS_11643_1986" },
4816 { 0x00050002, "CNS_11643_1992" },
4817 { 0x0005000A, "CNS_EUCTW_1991" },
4818 { 0x00050010, "CNS_EUCTW_1993" },
4819 { 0x000B0001, "TIS_620_2529" },
4820 { 0x000D0001, "TTB_CCDC" },
4821 { 0x05000010, "OSF_JAPANESE_UJIS" },
4822 { 0x05000011, "OSF_JAPANESE_SJIS_1" },
4823 { 0x05000012, "OSF_JAPANESE_SJIS_2" },
4824 { 0x05010001, "XOPEN_UTF_8" },
4825 { 0x05020001, "JVC_EUCJP" },
4826 { 0x05020002, "JVC_SJIS" },
4827 { 0x10000001, "DEC_KANJI" },
4828 { 0x10000002, "SUPER_DEC_KANJI" },
4829 { 0x10000003, "DEC_SHIFT_JIS" },
4830 { 0x10010001, "HP_ROMAN8" },
4831 { 0x10010002, "HP_KANA8" },
4832 { 0x10010003, "HP_ARABIC8" },
4833 { 0x10010004, "HP_GREEK8" },
4834 { 0x10010005, "HP_HEBREW8" },
4835 { 0x10010006, "HP_TURKISH8" },
4836 { 0x10010007, "HP15CN" },
4837 { 0x10010008, "HP_BIG5" },
4838 { 0x10010009, "HP_JAPANESE15__SJIS_" },
4839 { 0x1001000A, "HP_SJISHI" },
4840 { 0x1001000B, "HP_SJISPC" },
4841 { 0x1001000C, "HP_UJIS" },
4842 { 0x10020025, "IBM_037" },
4843 { 0x10020111, "IBM_273" },
4844 { 0x10020115, "IBM_277" },
4845 { 0x10020116, "IBM_278" },
4846 { 0x10020118, "IBM_280" },
4847 { 0x1002011A, "IBM_282" },
4848 { 0x1002011C, "IBM_284" },
4849 { 0x1002011D, "IBM_285" },
4850 { 0x10020122, "IBM_290" },
4851 { 0x10020129, "IBM_297" },
4852 { 0x1002012C, "IBM_300" },
4853 { 0x1002012D, "IBM_301" },
4854 { 0x100201A4, "IBM_420" },
4855 { 0x100201A8, "IBM_424" },
4856 { 0x100201B5, "IBM_437" },
4857 { 0x100201F4, "IBM_500" },
4858 { 0x10020341, "IBM_833" },
4859 { 0x10020342, "IBM_834" },
4860 { 0x10020343, "IBM_835" },
4861 { 0x10020344, "IBM_836" },
4862 { 0x10020345, "IBM_837" },
4863 { 0x10020346, "IBM_838" },
4864 { 0x10020347, "IBM_839" },
4865 { 0x10020352, "IBM_850" },
4866 { 0x10020354, "IBM_852" },
4867 { 0x10020357, "IBM_855" },
4868 { 0x10020358, "IBM_856" },
4869 { 0x10020359, "IBM_857" },
4870 { 0x1002035D, "IBM_861" },
4871 { 0x1002035E, "IBM_862" },
4872 { 0x1002035F, "IBM_863" },
4873 { 0x10020360, "IBM_864" },
4874 { 0x10020362, "IBM_866" },
4875 { 0x10020364, "IBM_868" },
4876 { 0x10020365, "IBM_869" },
4877 { 0x10020366, "IBM_870" },
4878 { 0x10020367, "IBM_871" },
4879 { 0x1002036A, "IBM_874" },
4880 { 0x1002036B, "IBM_875" },
4881 { 0x10020370, "IBM_880" },
4882 { 0x1002037B, "IBM_891" },
4883 { 0x10020380, "IBM_896" },
4884 { 0x10020381, "IBM_897" },
4885 { 0x10020387, "IBM_903" },
4886 { 0x10020388, "IBM_904" },
4887 { 0x10020396, "IBM_918" },
4888 { 0x10020399, "IBM_921" },
4889 { 0x1002039A, "IBM_922" },
4890 { 0x1002039E, "IBM_926" },
4891 { 0x1002039F, "IBM_927" },
4892 { 0x100203A0, "IBM_928" },
4893 { 0x100203A1, "IBM_929" },
4894 { 0x100203A2, "IBM_930" },
4895 { 0x100203A4, "IBM_932" },
4896 { 0x100203A5, "IBM_933" },
4897 { 0x100203A6, "IBM_934" },
4898 { 0x100203A7, "IBM_935" },
4899 { 0x100203A8, "IBM_936" },
4900 { 0x100203A9, "IBM_937" },
4901 { 0x100203AA, "IBM_938" },
4902 { 0x100203AB, "IBM_939" },
4903 { 0x100203AD, "IBM_941" },
4904 { 0x100203AE, "IBM_942" },
4905 { 0x100203AF, "IBM_943" },
4906 { 0x100203B2, "IBM_946" },
4907 { 0x100203B3, "IBM_947" },
4908 { 0x100203B4, "IBM_948" },
4909 { 0x100203B5, "IBM_949" },
4910 { 0x100203B6, "IBM_950" },
4911 { 0x100203B7, "IBM_951" },
4912 { 0x100203BB, "IBM_955" },
4913 { 0x100203C4, "IBM_964" },
4914 { 0x100203CA, "IBM_970" },
4915 { 0x100203EE, "IBM_1006" },
4916 { 0x10020401, "IBM_1025" },
4917 { 0x10020402, "IBM_1026" },
4918 { 0x10020403, "IBM_1027" },
4919 { 0x10020410, "IBM_1040" },
4920 { 0x10020411, "IBM_1041" },
4921 { 0x10020413, "IBM_1043" },
4922 { 0x10020416, "IBM_1046" },
4923 { 0x10020417, "IBM_1047" },
4924 { 0x10020440, "IBM_1088" },
4925 { 0x10020449, "IBM_1097" },
4926 { 0x1002044A, "IBM_1098" },
4927 { 0x10020458, "IBM_1112" },
4928 { 0x1002045A, "IBM_1114" },
4929 { 0x1002045B, "IBM_1115" },
4930 { 0x10020462, "IBM_1122" },
4931 { 0x100204E2, "IBM_1250" },
4932 { 0x100204E3, "IBM_1251" },
4933 { 0x100204E4, "IBM_1252" },
4934 { 0x100204E5, "IBM_1253" },
4935 { 0x100204E6, "IBM_1254" },
4936 { 0x100204E7, "IBM_1255" },
4937 { 0x100204E8, "IBM_1256" },
4938 { 0x100204E9, "IBM_1257" },
4939 { 0x10020564, "IBM_1380" },
4940 { 0x10020565, "IBM_1381" },
4941 { 0x10020567, "IBM_1383" },
4942 { 0x1002112C, "IBM_4396" },
4943 { 0x10021352, "IBM_4946" },
4944 { 0x10021354, "IBM_4948" },
4945 { 0x10021357, "IBM_4951" },
4946 { 0x10021358, "IBM_4952" },
4947 { 0x10021359, "IBM_4953" },
4948 { 0x10021360, "IBM_4960" },
4949 { 0x10021364, "IBM_4964" },
4950 { 0x10021365, "IBM_4965" },
4951 { 0x100213A2, "IBM_5026" },
4952 { 0x100213A7, "IBM_5031" },
4953 { 0x100213AB, "IBM_5035" },
4954 { 0x100213B8, "IBM_5048" },
4955 { 0x100213B9, "IBM_5049" },
4956 { 0x100213CB, "IBM_5067" },
4957 { 0x100221A4, "IBM_8612" },
4958 { 0x10022341, "IBM_9025" },
4959 { 0x10022342, "IBM_9026" },
4960 { 0x10022346, "IBM_9030" },
4961 { 0x10022360, "IBM_9056" },
4962 { 0x1002236A, "IBM_9066" },
4963 { 0x100223A5, "IBM_9125" },
4964 { 0x10026352, "IBM_25426" },
4965 { 0x10026358, "IBM_25432" },
4966 { 0x10026412, "IBM_1042" },
4967 { 0x10027025, "IBM_28709" },
4968 { 0x10028358, "IBM_33624" },
4969 { 0x100283BA, "IBM_33722" },
4970 { 0x10030001, "HTCSJIS" },
4971 { 0x10030002, "HTCUJIS" },
4972 { 0x10040001, "FUJITSU_U90" },
4973 { 0x10040002, "FUJITSU_S90" },
4974 { 0x10040003, "FUJITSU_R90" },
4975 { 0x10040004, "EBCDIC_ASCII_AND_JEF" },
4976 { 0x10040005, "EBCDIC_KATAKANA_AND_JEF" },
4977 { 0x10040006, "EBCDIC_JAPANESE_ENGLISH_AND_JEF" },
4981 static void decode_CodeSets(tvbuff_t *tvb, proto_tree *tree, int *offset,
4982 gboolean stream_is_be, guint32 boundary) {
4984 /* The boundary being passed in is the offset where the context_data
4985 * sequence begins. */
4987 guint32 code_set_id;
4989 /* We pass in -boundary, because the alignment is calculated relative to
4990 the beginning of the context_data sequence.
4991 Inside get_CDR_ulong(), the calculation will be (offset +(- boundary)) % 4
4992 to determine the correct alignment of the short. */
4993 code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
4995 proto_tree_add_text (tree, tvb, *offset - 4, 4,
4996 "char_data: 0x%08x %s", code_set_id, val_to_str(code_set_id, giop_code_set_vals, "Unknown (%u)") );
4998 code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
5000 proto_tree_add_text (tree, tvb, *offset - 4, 4,
5001 "wchar_data: 0x%08x %s", code_set_id, val_to_str(code_set_id, giop_code_set_vals, "Unknown (%u)") );
5008 * From Section 2.7.3 of the Real-time CORBA 1.1 Standard, the CORBA priority
5009 * is represented in the GIOP service request as:
5012 * typedef short ServiceId;
5013 * const ServiceId RTCorbaPriority = 10;
5016 * The RT-CORBA priority is a CDR encoded short value in a sequence<octet>
5019 static void decode_RTCorbaPriority(tvbuff_t *tvb, proto_tree *tree, int *offset,
5020 gboolean stream_is_be, guint32 boundary) {
5022 /* The boundary being passed in is the offset where the context_data
5023 * sequence begins. */
5027 /* RTCorbaPriority is stored as a CDR encoded short */
5028 /* We pass in -boundary, because the alignment is calculated relative to
5029 the beginning of the context_data sequence.
5030 Inside get_CDR_short(), the calculation will be (offset + (- boundary)) % 2
5031 to determine the correct alignment of the short. */
5032 rtpriority = get_CDR_short(tvb, offset, stream_is_be, -((gint32) boundary) );
5035 /* Highlight all of context_data except for the first endian byte */
5036 proto_tree_add_text (tree, tvb, *offset - 2, 2,
5037 "RTCorbaPriority: %d", rtpriority);
5042 static void decode_UnknownServiceContext(tvbuff_t *tvb, proto_tree *tree, int *offset,
5043 gboolean stream_is_be, guint32 boundary) {
5045 guint32 context_data_len;
5046 gchar *p_context_data;
5047 gchar *context_data;
5049 /* get sequence length, and NO encapsulation */
5050 context_data_len = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
5053 /* return if zero length sequence */
5054 if(context_data_len == 0)
5058 * Now decode sequence according to vendor ServiceId, but I dont
5059 * have that yet, so just dump it as data.
5062 /* fetch all octets in this sequence */
5064 get_CDR_octet_seq(tvb, &context_data, offset, context_data_len);
5066 /* Make a printable string */
5068 p_context_data = make_printable_string( context_data, context_data_len );
5071 proto_tree_add_text (tree, tvb, *offset - context_data_len , context_data_len,
5072 "context_data: %s", p_context_data);
5075 g_free(context_data);
5076 g_free(p_context_data);
5084 * typedef unsigned long ServiceID;
5086 * struct ServiceContext {
5087 * ServiceID context_id;
5088 * sequence <octet> context_data;
5090 * typedef sequence <ServiceContext> ServiceContextList;
5093 * Note: Spec says context_data is an encapsulation.
5098 void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *ptree, int *offset,
5099 gboolean stream_is_be, guint32 boundary) {
5101 guint32 seqlen; /* sequence length */
5102 guint32 context_data_len; /* context data sequence length */
5104 proto_tree *tree = NULL; /* ServiceContext tree */
5105 proto_tree *sub_tree1 = NULL;
5106 proto_item *tf = NULL, *tf_st1;
5111 guint32 vscid; /* Vendor Service context id */
5113 const gchar *service_context_name;
5114 gboolean encapsulation_is_be;
5115 guint32 encapsulation_boundary;
5116 int temp_offset, temp_offset1;
5117 int start_offset = *offset;
5119 /* create a subtree */
5122 /* set length to 0 now and correct with proto_item_set_len() later */
5123 tf = proto_tree_add_text (ptree, tvb, *offset, 0, "ServiceContextList");
5125 tree = proto_item_add_subtree (tf, ett_giop_scl);
5128 /* Get sequence length (number of elements) */
5129 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
5132 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5133 *offset-sizeof(seqlen),4,seqlen);
5136 /* return if zero length sequence */
5140 if (*offset - start_offset <= 0)
5141 THROW(ReportedBoundsError);
5142 proto_item_set_len(tf, *offset - start_offset);
5148 /* Loop for all ServiceContext's */
5150 for (i=0; i<seqlen; i++) {
5152 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
5153 vscid = (context_id & 0xffffff00) >> 8; /* vendor info, top 24 bits */
5154 scid = context_id & 0x000000ff; /* standard service info, lower 8 bits */
5157 proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
5158 *offset-sizeof(guint32),4,vscid);
5160 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
5161 *offset-sizeof(guint32),4,scid);
5165 if( vscid == 0) { /* OMG specified */
5166 service_context_name = val_to_str(scid, service_context_ids, "(0x%x)");
5167 } else { /* Proprietary vscid */
5168 service_context_name = "Unknown";
5172 proto_tree_add_text (tree, tvb, *offset -sizeof(context_id), 4,
5173 "Service Context ID: %s (%u)", service_context_name,
5177 temp_offset1 = *offset;
5178 /* The OMG has vscid of 0 reserved */
5179 if( vscid != 0 || scid > max_service_context_id ) {
5180 decode_UnknownServiceContext(tvb, tree, offset, stream_is_be, boundary);
5184 temp_offset = *offset;
5185 /* get sequence length, new endianness and boundary for encapsulation */
5186 context_data_len = get_CDR_encap_info(tvb, sub_tree1, offset,
5187 stream_is_be, boundary,
5188 &encapsulation_is_be , &encapsulation_boundary);
5191 tf_st1 = proto_tree_add_text (tree, tvb, temp_offset, sizeof(context_data_len) + context_data_len , service_context_name);
5192 sub_tree1 = proto_item_add_subtree (tf_st1, ett_giop_scl_st1);
5195 if (context_data_len == 0)
5198 /* See CORBA 3.0.2 standard, section Section 15.3.3 "Encapsulation",
5199 * for how CDR types can be marshalled into a sequence<octet>.
5200 * The first octet in the sequence determines endian order,
5201 * 0 == big-endian, 1 == little-endian
5206 case 0x01: /* Codesets */
5207 decode_CodeSets(tvb, sub_tree1, offset,
5208 encapsulation_is_be, encapsulation_boundary);
5210 case 0x0a: /* RTCorbaPriority */
5211 decode_RTCorbaPriority(tvb, sub_tree1, offset,
5212 encapsulation_is_be, encapsulation_boundary);
5216 /* Need to fill these in as we learn them */
5217 *offset = temp_offset1;
5218 decode_UnknownServiceContext(tvb, sub_tree1, offset, stream_is_be,
5222 /* Set the offset to the end of the context_data sequence */
5223 *offset = temp_offset1 + sizeof(context_data_len) + context_data_len;
5228 if (*offset - start_offset <= 0)
5229 THROW(ReportedBoundsError);
5230 proto_item_set_len(tf, *offset - start_offset);
5235 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
5238 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
5239 gboolean stream_is_big_endian,
5242 guint32 length; /* string length */
5243 guint32 minor_code_value;
5244 guint32 completion_status;
5246 gchar *buf; /* pointer to string buffer */
5248 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
5251 proto_tree_add_text(tree, tvb, *offset-4, 4,
5252 "Exception length: %u", length);
5254 proto_tree_add_text(tree, tvb, *offset - length, length,
5255 "Exception id: %s", buf );
5260 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
5261 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
5264 proto_tree_add_text(tree, tvb, *offset-8, 4,
5265 "Minor code value: %u", minor_code_value);
5266 proto_tree_add_text(tree, tvb, *offset-4, 4,
5267 "Completion Status: %u", completion_status);
5273 * Helper functions for dissecting TypeCodes
5275 * These functions decode the complex parameter lists
5276 * of TypeCodes as defined in the CORBA spec chapter 15.
5279 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5280 gboolean stream_is_big_endian, guint32 boundary) {
5282 guint32 new_boundary; /* new boundary for encapsulation */
5283 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5285 guint32 seqlen; /* sequence length */
5287 /* get sequence length, new endianness and boundary for encapsulation */
5288 seqlen = get_CDR_encap_info(tvb, tree, offset,
5289 stream_is_big_endian, boundary,
5290 &new_stream_is_big_endian, &new_boundary);
5292 /* get repository ID */
5293 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5297 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5298 hf_giop_typecode_name);
5303 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5304 gboolean stream_is_big_endian, guint32 boundary,
5305 MessageHeader * header ) {
5307 guint32 new_boundary; /* new boundary for encapsulation */
5308 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5310 guint32 count; /* parameter count (of tuples) */
5311 guint32 seqlen; /* sequence length */
5312 guint32 i; /* loop index */
5314 /* get sequence lengt,h new endianness and boundary for encapsulation */
5315 seqlen = get_CDR_encap_info(tvb, tree, offset,
5316 stream_is_big_endian, boundary,
5317 &new_stream_is_big_endian, &new_boundary);
5319 /* get repository ID */
5320 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5324 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5325 hf_giop_typecode_name);
5327 /* get count of tuples */
5328 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5330 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5331 *offset-sizeof(count),4,count);
5334 /* get all tuples */
5335 for (i=0; i< count; i++) {
5336 /* get member name */
5337 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5338 hf_giop_typecode_member_name);
5340 /* get member type */
5341 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5347 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5348 gboolean stream_is_big_endian, guint32 boundary,
5349 MessageHeader * header) {
5351 guint32 new_boundary; /* new boundary for encapsulation */
5352 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5354 guint32 TCKind; /* TypeCode */
5355 gint32 s_octet4; /* signed int32 */
5357 guint32 count; /* parameter count (of tuples) */
5358 guint32 seqlen; /* sequence length */
5359 guint32 i; /* loop index */
5361 /* get sequence legnth, new endianness and boundary for encapsulation */
5362 seqlen = get_CDR_encap_info(tvb, tree, offset,
5363 stream_is_big_endian, boundary,
5364 &new_stream_is_big_endian, &new_boundary);
5366 /* get repository ID */
5367 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5371 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5372 hf_giop_typecode_name);
5374 /* get discriminant type */
5375 TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5377 /* get default used */
5378 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
5380 proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
5381 *offset-sizeof(s_octet4),4,s_octet4);
5383 /* get count of tuples */
5384 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5386 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5387 *offset-sizeof(count),4,count);
5390 /* get all tuples */
5391 for (i=0; i< count; i++) {
5392 /* get label value, based on TCKind above */
5393 dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
5395 /* get member name */
5396 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5397 hf_giop_typecode_member_name);
5399 /* get member type */
5400 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5406 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5407 gboolean stream_is_big_endian, guint32 boundary) {
5409 guint32 new_boundary; /* new boundary for encapsulation */
5410 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5412 guint32 count; /* parameter count (of tuples) */
5413 guint32 seqlen; /* sequence length */
5414 guint32 i; /* loop index */
5416 /* get sequence length, new endianness and boundary for encapsulation */
5417 seqlen = get_CDR_encap_info(tvb, tree, offset,
5418 stream_is_big_endian, boundary,
5419 &new_stream_is_big_endian, &new_boundary);
5421 /* get repository ID */
5422 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5426 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5427 hf_giop_typecode_name);
5429 /* get count of tuples */
5430 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5432 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5433 *offset-sizeof(count),4,count);
5436 /* get all tuples */
5437 for (i=0; i< count; i++) {
5438 /* get member name */
5439 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5440 hf_giop_typecode_member_name);
5446 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5447 gboolean stream_is_big_endian, guint32 boundary,
5448 MessageHeader * header) {
5450 guint32 new_boundary; /* new boundary for encapsulation */
5451 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5453 guint32 u_octet4; /* unsigned int32 */
5455 guint32 seqlen; /* sequence length */
5457 /* get sequence length, new endianness and boundary for encapsulation */
5458 seqlen = get_CDR_encap_info(tvb, tree, offset,
5459 stream_is_big_endian, boundary,
5460 &new_stream_is_big_endian, &new_boundary);
5462 /* get element type */
5463 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5465 /* get max length */
5466 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5468 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
5469 *offset-sizeof(u_octet4),4,u_octet4);
5474 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5475 gboolean stream_is_big_endian, guint32 boundary,
5476 MessageHeader * header) {
5478 guint32 new_boundary; /* new boundary for encapsulation */
5479 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5481 guint32 u_octet4; /* unsigned int32 */
5483 guint32 seqlen; /* sequence length */
5485 /* get sequence length, new endianness and boundary for encapsulation */
5486 seqlen = get_CDR_encap_info(tvb, tree, offset,
5487 stream_is_big_endian, boundary,
5488 &new_stream_is_big_endian, &new_boundary);
5490 /* get element type */
5491 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5494 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5496 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5497 *offset-sizeof(u_octet4),4,u_octet4);
5502 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5503 gboolean stream_is_big_endian, guint32 boundary,
5504 MessageHeader * header) {
5506 guint32 new_boundary; /* new boundary for encapsulation */
5507 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5509 guint32 seqlen; /* sequence length */
5511 /* get sequence legnth, new endianness and boundary for encapsulation */
5512 seqlen = get_CDR_encap_info(tvb, tree, offset,
5513 stream_is_big_endian, boundary,
5514 &new_stream_is_big_endian, &new_boundary);
5516 /* get repository ID */
5517 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5521 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5522 hf_giop_typecode_name);
5524 /* get ??? (noname) TypeCode */
5525 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5530 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5531 gboolean stream_is_big_endian, guint32 boundary,
5532 MessageHeader * header) {
5534 guint32 new_boundary; /* new boundary for encapsulation */
5535 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5537 guint32 count; /* parameter count (of tuples) */
5538 guint32 seqlen; /* sequence length */
5539 guint32 i; /* loop index */
5541 /* get sequence length, new endianness and boundary for encapsulation */
5542 seqlen = get_CDR_encap_info(tvb, tree, offset,
5543 stream_is_big_endian, boundary,
5544 &new_stream_is_big_endian, &new_boundary);
5546 /* get repository ID */
5547 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5551 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5552 hf_giop_typecode_name);
5554 /* get count of tuples */
5555 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5557 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5558 *offset-sizeof(count),4,count);
5561 /* get all tuples */
5562 for (i=0; i< count; i++) {
5563 /* get member name */
5564 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5565 hf_giop_typecode_member_name);
5567 /* get member type */
5568 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5574 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5575 gboolean stream_is_big_endian, guint32 boundary,
5576 MessageHeader * header) {
5578 guint32 new_boundary; /* new boundary for encapsulation */
5579 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5581 gint16 s_octet2; /* signed int16 */
5583 guint32 count; /* parameter count (of tuples) */
5584 guint32 seqlen; /* sequence length */
5585 guint32 i; /* loop index */
5587 /* get sequence length, new endianness and boundary for encapsulation */
5588 seqlen = get_CDR_encap_info(tvb, tree, offset,
5589 stream_is_big_endian, boundary,
5590 &new_stream_is_big_endian, &new_boundary);
5592 /* get repository ID */
5593 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5597 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5598 hf_giop_typecode_name);
5600 /* get ValueModifier */
5601 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5603 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5604 *offset-sizeof(s_octet2),2,s_octet2);
5607 /* get conrete base */
5608 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5610 /* get count of tuples */
5611 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5613 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5614 *offset-sizeof(count),4,count);
5617 /* get all tuples */
5618 for (i=0; i< count; i++) {
5619 /* get member name */
5620 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5621 hf_giop_typecode_member_name);
5623 /* get member type */
5624 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5626 /* get Visibility */
5627 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5629 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5630 *offset-sizeof(s_octet2),2,s_octet2);
5637 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5638 gboolean stream_is_big_endian, guint32 boundary,
5639 MessageHeader * header) {
5641 guint32 new_boundary; /* new boundary for encapsulation */
5642 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5644 guint32 seqlen; /* sequence length */
5646 /* get sequence length, new endianness and boundary for encapsulation */
5647 seqlen = get_CDR_encap_info(tvb, tree, offset,
5648 stream_is_big_endian, boundary,
5649 &new_stream_is_big_endian, &new_boundary);
5651 /* get repository ID */
5652 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5656 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5657 hf_giop_typecode_name);
5659 /* get ??? (noname) TypeCode */
5660 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5664 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5665 gboolean stream_is_big_endian, guint32 boundary) {
5667 guint32 new_boundary; /* new boundary for encapsulation */
5668 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5670 guint32 seqlen; /* sequence length */
5672 /* get sequence length, new endianness and boundary for encapsulation */
5673 seqlen = get_CDR_encap_info(tvb, tree, offset,
5674 stream_is_big_endian, boundary,
5675 &new_stream_is_big_endian, &new_boundary);
5677 /* get repository ID */
5678 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5682 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5683 hf_giop_typecode_name);
5688 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5689 gboolean stream_is_big_endian, guint32 boundary) {
5691 guint32 new_boundary; /* new boundary for encapsulation */
5692 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5694 guint32 seqlen; /* sequence length */
5696 /* get sequence length, new endianness and boundary for encapsulation */
5697 seqlen = get_CDR_encap_info(tvb, tree, offset,
5698 stream_is_big_endian, boundary,
5699 &new_stream_is_big_endian, &new_boundary);
5701 /* get repository ID */
5702 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5706 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5707 hf_giop_typecode_name);
5711 /* Typecode parameter lists are encoded as encapsulations and
5712 * this function gets the encapsulation information; see
5713 * CORBA spec chapter 15
5716 * Renamed to get_CDR_encap_info() for any encapsulation
5717 * we come across, useful helper function
5719 * Also, should return immediately if seqlen == 0.
5720 * ie: Forget about trying to grab endianess for
5721 * zero length sequence.
5723 * Caller must always check seqlen == 0, and not assume its value
5726 * Note: there seemed to be considerable confusion in corba
5727 * circles as to the correct interpretation of encapsulations,
5728 * and zero length sequences etc, but this is our best bet at the
5735 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5736 gboolean old_stream_is_big_endian, guint32 old_boundary,
5737 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5739 guint32 seqlen; /* sequence length */
5740 guint8 giop_endianess;
5742 /* Get sequence length of parameter list */
5743 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5745 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5746 *offset-sizeof(seqlen),4,seqlen);
5752 * seqlen == 0, implies no endianess and no data
5753 * so just return. Populate new_boundary_ptr and
5754 * new_stream_is_big_endian_ptr with current (old)
5755 * values, just to keep everyone happy. -- FS
5761 *new_boundary_ptr = old_boundary;
5762 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5768 /* Start of encapsulation of parameter list */
5769 *new_boundary_ptr = *offset; /* remember */
5770 giop_endianess = get_CDR_octet(tvb,offset);
5772 *new_stream_is_big_endian_ptr = ! giop_endianess;
5775 * Glib: typedef gint gboolean;
5776 * ie: It is not a guint8, so cannot use sizeof to correctly
5782 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5783 *offset-1,1,giop_endianess);
5793 * gets a TypeCode complex string parameter and
5794 * displays it in the relevant tree.
5797 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5798 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5800 guint32 u_octet4; /* unsigned int32 */
5801 gchar *buf; /* ptr to string buffer */
5804 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5807 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5808 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5810 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5814 g_free(buf); /* dont forget */
5819 * For a given data type, given by a TypeCode gets the associated data
5820 * and displays it in the relevant tree.
5823 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5824 gboolean stream_is_big_endian, guint32 boundary,
5825 MessageHeader * header, guint32 data_type ) {
5827 gboolean my_boolean; /* boolean */
5829 gint8 s_octet1; /* signed int8 */
5830 guint8 u_octet1; /* unsigned int8 */
5832 gint16 s_octet2; /* signed int16 */
5833 guint16 u_octet2; /* unsigned int16 */
5835 gint32 s_octet4; /* signed int32 */
5836 guint32 u_octet4; /* unsigned int32 */
5838 gdouble my_double; /* double */
5839 gfloat my_float; /* float */
5841 gchar *buf = NULL; /* ptr to string buffer */
5843 /* Grab the data according to data type */
5845 switch (data_type) {
5847 /* nothing to decode */
5850 /* nothing to decode */
5853 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5855 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5856 *offset-sizeof(s_octet2),2,s_octet2);
5860 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5862 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5863 *offset-sizeof(s_octet4),4,s_octet4);
5867 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5869 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5870 *offset-sizeof(u_octet2),2,u_octet2);
5874 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5876 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5877 *offset-sizeof(u_octet4),4,u_octet4);
5881 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5883 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5884 *offset-sizeof(my_float),4,my_float);
5888 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5890 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5891 *offset-sizeof(my_double),8,my_double);
5895 my_boolean = get_CDR_boolean(tvb,offset);
5897 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5898 *offset-1,1,my_boolean);
5902 u_octet1 = get_CDR_char(tvb,offset);
5904 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5905 *offset-sizeof(u_octet1),1,u_octet1);
5909 u_octet1 = get_CDR_octet(tvb,offset);
5911 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5912 *offset-sizeof(u_octet1),1,u_octet1);
5916 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5919 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5930 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5932 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5933 *offset-sizeof(u_octet4),4,u_octet4);
5937 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5939 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5940 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5942 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5943 *offset-u_octet4,u_octet4,buf);
5947 g_free(buf); /* dont forget */
5964 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5967 * XXX - can any of these throw an exception?
5968 * If so, we need to catch the exception and free "buf".
5970 if (s_octet1 < 0) { /* no size to add to tree */
5971 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5972 *offset+s_octet1,(-s_octet1),buf);
5974 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5975 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5976 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5977 *offset-s_octet1,s_octet1,buf);
5981 g_free(buf); /* dont forget */
5984 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5987 * XXX - can any of these throw an exception?
5988 * If so, we need to catch the exception and free "buf".
5990 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5991 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5992 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5993 *offset-u_octet4,u_octet4,buf);
5996 g_free(buf); /* dont forget */
6006 case tk_abstract_interface:
6009 g_warning("giop: Unknown typecode data type %u \n", data_type);