2 * Routines for CORBA GIOP/IIOP packet disassembly
5 * Laurent Deniel <deniel@worldnet.fr>
6 * Craig Rodrigues <rodrigc@mediaone.net>
8 * GIOP API extensions by,
9 * Frank Singleton <frank.singleton@ericsson.com>
10 * Trevor Shepherd <eustrsd@am1.ericsson.se>
12 * $Id: packet-giop.c,v 1.58 2002/04/24 21:28:52 guy Exp $
14 * Ethereal - Network traffic analyzer
15 * By Gerald Combs <gerald@ethereal.com>
16 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 * 1. heuristic giop dissector table [started]
37 * 2. GUI options, see 20
38 * 3. Remove unneccessary reply_status in heuristic dissector calls (now
39 * part of MessageHeader) [done]
40 * 4. get_CDR_xxx should be passed an alignment offset value
41 * rather than GIOP_HEADER_SIZE, as alignment can also change in a
42 * octet stream when eg: encapsulation is used [done]
43 * 5. GIOP users should eventually get there own tvbuff, and
44 * not rely on the GIOP tvbuff, more robust
45 * 6. get_CDR_string,wchar,wstring etc should handle different
46 * GIOP versions [started]
47 * 7. Fix situation where req_id is not unique in a logfile [done, use FN/MFN, needs improving.]
49 * 8. Keep request_1_2 in step with request_1_1 [started]
50 * 9. Explicit module name dissection [done]
51 * 10. Decode IOR and put in a useful struct [IOR decode started]
52 * 11. Fix encapsulation of IOR etc and boundary [done]
53 * 12. handle get_CDR_typeCode() [started]
54 * 13. Handle different IOR profiles
55 * 14. Change printable_string to RETURN a new string, not to modify the old.
56 * or, new function, make_printable_string [done, make_printable_string]
58 * 15. Handle "TCKind", and forget about eg: enum translation to symbolic values
59 * otherwise need knowledge of sub dissectors data - YUK [done]
60 * 16. Handle multiple RepoId representations, besides IDL:Echo:1.0 (see 13.)
61 * 17. Pass subset of RepoID to explicit dissector.
62 * eg : If IDL:Mod1/Mod2/Int3:1.0 then pass "Mod1/Mode2/Int3" to sub dissector[done]
63 * 18. Better hashing algorithms
64 * 19. Handle hash collision properly .
65 * 20. Allow users to paste a stringified IOR into the GUI, and tie it
67 * 21. Add complete_request_packet_list and complete_reply_packet_hash.[done]
68 * 22. Handle case where users click in any order, AND try and match
69 * REPLY msg to the correct REQUEST msg when we have a request_id collision.[done]
70 * 23. Clean up memory management for all those g_malloc's etc
71 * 24. register_giop_user_module could return a key for every distinct Module/Interface
72 * the sub_dissector uses. So, instead of strcmp()'s when handling the
73 * namespace of an operation, we could have a lookup table instead.
74 * 25. A few typedefs in the right place.
75 * 26 Improve handling of gchar * and use const gchar * where possible.
76 * 27. Read/write IOR etc to/from file, allows objkey hash to be built from
77 * external data [read done, write incomplete]
78 * 28. Call sub dissector only if tvb_offset_exists(). [Done, this is checked
79 * inside try_explicit_giop_dissector() ]
81 * 29. Make add/delete routine for objkey hash as it may be useful when say reading
82 * stringified IOR's from a file to add them to our hash. ie: There are other ways
83 * to populate our object key hash besides REPLY's to RESOLVE(request) [done]
85 * 30. Add routine to encode/decode stringified IOR's [decode done]
86 * 31. Add routine to read IOR's from file [done]
87 * 32. TypeCode -none-, needs decoding.
88 * 33. Complete dissect_data_for_typecode.
89 * 34. For complex TypeCodes need to check final offset against original offset + sequence length.
90 * 35. Update REQUEST/REPLY 1_2 according to IDL (eg; ServiceContextList etc).
91 * 36. Adding decode_ServiceContextList, incomplete.
92 * 37. Helper functions should not ALWAYS rely on header to find current endianess. It should
93 * be passed from user, eg Use stream_is_big_endian. [started]
94 * 38. Remove unwanted/unused function parameters, see decode_IOR [started]
95 * 40. Add sequence <IOP::TaggedComponent> components to IIOP IOR profile. Perhaps
96 * decode_IOP_TaggedComponents as a helper function. [done - NOT helper]
98 * 41. Make important field searchable from Message header. ie: Remove add_text_
99 * 42. Use sub-tree for decode_ServiceContextList, looks better.
100 * 43. dissect_reply_body, no exception dissector calls
101 * - call subdiss directly, as we already have handle.
102 * - add repoid to heuristic call also.
104 * 44. typedef using xxx_t in .h file.
105 * 45. Subdissectors should not be passed MessageHeader to find endianness and
106 * version, they should be passed directly ?
107 * 46. get_CDR_wchar and wstring need wide chars decoded (just dumped in
108 * any readable form at present, not handled well at all, suggestions welcome -- FS
109 * 47. Change ...add_text to ...add_xxx (ie use hf fields).
111 * 48. BUG - file load with a GIOP filter set, causes the FN/MFN data struct to be
112 * not initiated properly. Hit "Reload" as a workaround, til I fix this -- FS
119 * Intended Decode strategy:
120 * =========================
124 * REQUEST: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
125 * and populate complete_request_packet_hash
127 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
132 * REQUEST: FN -> giop_sub_handle_t directly (via complete_request_packet_hash)
134 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
135 * (via complete_request_packet_hash
141 * 1. Request_ID's are unique only per connection.
143 * 2. You must be monitoring the network when the client does
144 * a REQUEST(resolve), otherwise I have no knowledge of the
145 * association between object_key and REPOID. I could talk to
146 * a Nameserver, but then I would start "generating" packets.
147 * This is probably not a good thing for a protocol analyser.
148 * Also, how could I decode logfiles offline.
150 * TODO -- Read stringified IORs from an input file.[done]
152 * 3. User clicks (REQUEST) is currently handle the same as
153 * the initial pass handling.
155 * ie: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
160 * Important Data Structures:
165 * This is a hash table that maps IDL Module/Interface Names (Key)
166 * to sub_dissector handles, giop_sub_handle_t. It is populated
167 * by subdissectors, via register_giop_user_module(). This
168 * table is used when we have a REPOID, and explicitly wish to
169 * call the subdissector that has registered responsibility for
170 * that IDL module/interface.
176 * This singly linked list is used to hold entries for
177 * heuristic based subdissectors. It is populated by sub_dissectors
178 * wishing to be called via heuristic mechanisms. They do this
179 * via the register_giop_user() function.
185 * This hash table maps object_key's (key) onto REPOID's (val).
186 * Once a client has REQUEST(resolve) an object , it knows about
187 * an object (interface) via its object_key (see IOR). So in order to follow
188 * packets that contain an object_key only, and to be able to forward it
189 * to the correct explicit subdissector, we need this table.
191 * So, I listen in on REQUEST(resolve) messages between client and
192 * Nameserver, and store the respones (REPLY/Objkey,Repo_ID) here.
194 * Also, stringified IOR's can be read from a file "IOR.txt" and used
195 * to populate this hash also.
198 * Other Data structures
199 * =======================
201 * These structures have been added to minimise the possibility
202 * of incorrectly interpreted packets when people click all
203 * over the place, in no particular order, when the request_id's are
204 * not unique as captured. If all request_is'd are unique, as captured, then
205 * we would not have to deal with this problem.
208 * When the logfile or packets are initially being processed, I will
209 * build 2 structures. The intent is to be able to map a REPLY message
210 * back to the most recent REQUEST message with the same Request_ID
211 * (TODO and matching port and IP address ??)
217 * MFN - Matching Frame Number
220 * complete_request_packet_list
221 * ----------------------------
223 * This is a list that contains ALL the FN's that are REQUEST's, along with
224 * operation,request_id and giop_sub_handle_t
226 * complete_reply_packet_hash
227 * --------------------------
229 * This is a hash table. It is populated with FN (key) and MFN (val).
230 * This allows me to handle the case, where if you click on any REPLY
231 * message, I can lookup the matching request. This can improve
232 * the match rate between REQUEST and REPLY when people click in
233 * any old fashion, but is NOT foolproof.
235 * The algorithm I use to populate this hash during initial pass,
238 * If packet is a REPLY, note the reqid, and then traverse backwards
239 * through the complete_request_packet_list from its tail, looking
240 * for a FN that has the same Request_id. Once found, take the found FN
241 * from complete_reply_packet_hash, and insert it into the MFN field
242 * of the complete_reply_packet_hash.
245 * See TODO for improvements to above algorithm.
247 * So now when people click on a REQUEST packet, I can call lookup the
248 * giop_sub_handle_t directly from complete_request_packet_list.
250 * And, when they click on a REPLY, I grab the MFN of this FN from
251 * complete_reply_packet_hash, then look that up in the complete_request_packet_list
252 * and call the sub_dissector directly.
254 * So, how do I differentiate between the initial processing of incoming
255 * packets, and a user clickin on one ? Good question.
257 * I leverage the pinfo_fd->flags.visited on a per frame
260 * To quote from the ever helpful development list
262 * " When a capture file is initially loaded, all "visited" flags
263 * are 0. Ethereal then makes the first pass through file,
264 * sequentially dissecting each packet. After the packet is
265 * dissected the first time, "visited" is 1. (See the end of
266 * dissect_packet() in epan/packet.c; that's the code that
267 * sets "visited" to 1).
269 * By the time a user clicks on a packet, "visited" will already
270 * be 1 because Ethereal will have already done its first pass
271 * through the packets.
273 * Reload acts just like a normal Close/Open, except that it
274 * doesn't need to ask for a filename. So yes, the reload button
275 * clears the flags and re-dissects the file, just as if the file
276 * had been "opened". "
285 #ifdef HAVE_SYS_TYPES_H
286 # include <sys/types.h>
295 #ifdef NEED_STRERROR_H
296 #include "strerror.h"
299 #include <epan/packet.h>
300 #include "packet-giop.h"
303 * This affects how we handle context_data inside ServiceContext structs.
304 * According to CORBA 2.4.2, Context data is encapsulated in octet sequences,
305 * but so far I haven't seen the that on the wire. But, maybe its me -- FS
309 #define CONTEXT_DATA_IS_ENCAPSULATED 0
313 * Set to 1 for DEBUG output - TODO make this a runtime option
321 * ------------------------------------------------------------------------------------------+
322 * Private Helper function Declarations
323 * ------------------------------------------------------------------------------------------+
327 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
328 guint32 boundary, gboolean new_endianess, gchar *repobuf,
329 gboolean store_flag);
331 static void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
332 gboolean stream_is_be, guint32 boundary);
334 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
335 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf);
337 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
338 guint32 boundary, gboolean stream_is_big_endian );
340 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
341 gboolean stream_is_big_endian,
344 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
345 gboolean stream_is_big_endian, guint32 boundary,
346 MessageHeader * header);
348 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
349 gboolean stream_is_big_endian, guint32 boundary,
350 MessageHeader * header);
352 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
353 gboolean stream_is_big_endian, guint32 boundary,
354 MessageHeader * header );
356 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
357 gboolean stream_is_big_endian, guint32 boundary,
358 MessageHeader * header);
360 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
361 gboolean stream_is_big_endian, guint32 boundary,
362 MessageHeader * header);
364 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
365 gboolean stream_is_big_endian, guint32 boundary,
366 MessageHeader * header);
368 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
369 gboolean stream_is_big_endian, guint32 boundary,
370 MessageHeader * header);
372 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
373 gboolean stream_is_big_endian, guint32 boundary,
374 MessageHeader * header);
376 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
377 gboolean stream_is_big_endian, guint32 boundary,
378 MessageHeader * header);
380 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
381 gboolean stream_is_big_endian, guint32 boundary,
382 MessageHeader * header);
384 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
385 gboolean stream_is_big_endian, guint32 boundary,
386 MessageHeader * header);
388 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
389 gboolean stream_is_big_endian, guint32 boundary,
390 MessageHeader * header);
393 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
394 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
396 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
397 gboolean stream_is_big_endian, guint32 boundary,
398 MessageHeader * header, guint32 data_type );
404 * ------------------------------------------------------------------------------------------+
405 * Data/Variables/Structs
406 * ------------------------------------------------------------------------------------------+
410 static int proto_giop = -1;
411 static int hf_giop_message_type = -1;
412 static int hf_giop_message_size = -1;
413 static int hf_giop_repoid = -1;
414 static int hf_giop_string_length = -1;
415 static int hf_giop_sequence_length = -1;
416 static int hf_giop_profile_id = -1;
417 static int hf_giop_type_id = -1;
418 static int hf_giop_iiop_v_maj = -1;
419 static int hf_giop_iiop_v_min = -1;
420 static int hf_giop_endianess = -1; /* esp encapsulations */
421 static int hf_giop_IOR_tag = -1;
422 static int hf_giop_IIOP_tag = -1;
424 static int hf_giop_TCKind = -1;
425 static int hf_giop_typecode_count = -1;
426 static int hf_giop_typecode_default_used = -1;
427 static int hf_giop_typecode_digits = -1;
428 static int hf_giop_typecode_length = -1;
429 static int hf_giop_typecode_max_length = -1;
430 static int hf_giop_typecode_member_name = -1;
431 static int hf_giop_typecode_name = -1;
432 static int hf_giop_typecode_scale = -1;
433 static int hf_giop_typecode_ValueModifier = -1;
434 static int hf_giop_typecode_Visibility = -1;
436 static int hf_giop_type_boolean = -1;
437 static int hf_giop_type_char = -1;
438 static int hf_giop_type_double = -1;
439 static int hf_giop_type_enum = -1;
440 static int hf_giop_type_float = -1;
441 static int hf_giop_type_long = -1;
442 static int hf_giop_type_octet = -1;
443 static int hf_giop_type_short = -1;
444 static int hf_giop_type_string = -1;
445 static int hf_giop_type_ulong = -1;
446 static int hf_giop_type_ushort = -1;
448 static int hf_giop_iiop_host = -1;
449 static int hf_giop_iiop_port = -1;
450 static int hf_giop_iop_vscid = -1;
451 static int hf_giop_iop_scid = -1;
457 static gint ett_giop = -1;
458 static gint ett_giop_reply = -1;
459 static gint ett_giop_request = -1;
460 static gint ett_giop_cancel_request = -1;
461 static gint ett_giop_locate_request = -1;
462 static gint ett_giop_locate_reply = -1;
463 static gint ett_giop_fragment = -1;
465 static gint ett_giop_scl = -1; /* ServiceContextList */
466 static gint ett_giop_ior = -1; /* IOR */
468 static dissector_handle_t data_handle;
471 static const value_string giop_endianess_vals[] = {
472 { 0x0, "Big Endian" },
473 { 0x1, "Little Endian" },
477 static const value_string sync_scope[] = {
478 { 0x0, "SYNC_NONE" },
479 { 0x1, "SYNC_WITH_TRANSPORT"},
480 { 0x2, "SYNC_WITH_SERVER"},
481 { 0x3, "SYNC_WITH_TARGET"},
487 static const value_string profile_id_vals[] = {
488 { 0x0, "TAG_INTERNET_IOP" },
489 { 0x1, "TAG_MULTIPLE_COMPONENTS"},
490 { 0x2, "TAG_SCCP_IOP"},
494 static const value_string giop_message_types[] = {
497 { 0x2, "CancelRequest"},
498 { 0x3, "LocateRequest"},
499 { 0x4, "LocateReply"},
500 { 0x5, "CloseConnection"},
501 { 0x6, "MessageError"},
506 static const value_string giop_locate_status_types[] = {
507 { 0x0, "Unknown Object" },
508 { 0x1, "Object Here"},
509 { 0x2, "Object Forward"},
510 { 0x3, "Object Forward Perm"},
511 { 0x4, "Loc System Exception"},
512 { 0x5, "Loc Needs Addressing Mode"},
516 static const value_string tckind_vals[] = {
529 { 12, "tk_TypeCode"},
530 { 13, "tk_Principal"},
536 { 19, "tk_sequence"},
540 { 23, "tk_longlong"},
541 { 24, "tk_ulonglong"},
542 { 25, "tk_longdouble"},
547 { 30, "tk_value_box"},
549 { 32, "tk_abstract_interface"},
555 #define GIOP_MAGIC "GIOP"
558 * TAGS for IOR Profiles
560 * Chapter 13 Corba 2.4.2
564 #define IOP_TAG_INTERNET_IOP 0
565 #define IOP_TAG_MULTIPLE_COMPONENTS 1
568 /* Max Supported versions */
570 static const guint GIOP_MAJOR = 1;
571 static const guint GIOP_MINOR = 2;
574 static const int KeyAddr = 0;
575 static const int ProfileAddr = 1;
576 static const int ReferenceAddr = 2;
580 static const value_string reply_status_types[] = {
581 { NO_EXCEPTION, "No Exception" } ,
582 { USER_EXCEPTION, "User Exception" } ,
583 { SYSTEM_EXCEPTION, "System Exception" } ,
584 { LOCATION_FORWARD, "Location Forward" } ,
585 { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
586 { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
592 typedef enum LocateStatusType
597 OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
598 LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
599 LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
603 typedef struct LocateReplyHeader
606 guint32 locate_status;
612 * DATA - complete_request_list
615 static GList *giop_complete_request_list;
617 struct comp_req_list_entry {
618 guint32 fn; /* frame number */
619 gchar * operation; /* echo echoString */
620 giop_sub_handle_t *subh; /* handle to sub dissector */
621 guint32 reqid; /* request id */
622 gchar * repoid; /* repository ID */
625 typedef struct comp_req_list_entry comp_req_list_entry_t;
629 * DATA - complete_reply_hash
631 * Maps reply FN to request MFN
634 static int complete_reply_hash_count = 1000; /* storage size for our permanent data */
635 /* ie: 1000 entries -- needs tweaking -- FS */
637 struct complete_reply_hash_key {
638 guint32 fn; /* reply frame number */
641 struct complete_reply_hash_val {
642 guint32 mfn; /* matching frame number (request) */
645 GHashTable *giop_complete_reply_hash = NULL; /* hash */
646 GMemChunk *giop_complete_reply_keys = NULL; /* key storage */
647 GMemChunk *giop_complete_reply_vals = NULL; /* val storage */
651 * DATA - Module Hash stuff to store data from register_giop_user_module
653 * ie: module (or interface ?) name, and ptr to sub_dissector handle
655 * With this knowledge, we can call a sub dissector directly,
658 * objkey -> repoid -> sub_dissector via registered module/interface
663 static int giop_module_init_count = 100; /* storage size for our permanent data */
664 /* ie: 100 entries -- needs tweaking -- FS */
666 struct giop_module_key {
667 gchar *module; /* module (interface?) name */
670 struct giop_module_val {
671 giop_sub_handle_t *subh; /* handle to sub dissector */
674 GHashTable *giop_module_hash = NULL; /* hash */
675 GMemChunk *giop_module_keys = NULL; /* key storage */
676 GMemChunk *giop_module_vals = NULL; /* val storage */
680 * DATA - GSList to store list of function (dissector) pointers.
681 * for heuristic dissection.
685 static GSList *giop_sub_list = NULL;
688 * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
689 * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
691 * With this knowledge, we can call a sub dissector directly later
694 * objkey -> repoid -> sub_dissector via registered module/interface
696 * rather than heuristic calls that do not provide operation context.
697 * (unless we pass the RepoID for a given objkey -- hmmm)
702 * Interesting operation list, add more if you want to save
706 static const char giop_op_resolve[] = "resolve";
707 static const char giop_op_bind_new_context[] = "bind_new_context";
708 static const char giop_op_bind[] = "bind";
711 * Enums for interesting local operations, that we may need to monitor
712 * with their subsequent replies
717 request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
718 request_bind_new_context_op_val, /* bind_new_context */
719 request_bind_op_val, /* bind */
720 request_get_INIT_op_val, /* finding Nameserver */
726 * hash for mapping object keys onto object namespaces, so
727 * I can call the correct dissector.
733 * Where did I get the IOR from.
737 req_res = 0, /* REQUEST (resolve) */
738 file, /* stringified IOR' in a file */
742 typedef enum ior_src ior_src_t;
747 * Enums for my lists and hash's
750 enum collection_data {
751 cd_heuristic_users = 0,
754 cd_complete_request_list,
755 cd_complete_reply_hash
758 typedef enum collection_data collection_data_t;
762 static int giop_objkey_init_count = 100; /* storage size for our permanent data */
763 /* ie: 100 entries -- needs tweaking -- FS */
765 struct giop_object_key {
766 guint8 *objkey; /* ptr to object key */
767 guint32 objkey_len; /* length */
770 struct giop_object_val {
771 guint8 *repo_id; /* ptr to Repository ID string */
772 ior_src_t src; /* where did Iget this IOR from */
775 GHashTable *giop_objkey_hash = NULL; /* hash */
776 GMemChunk *giop_objkey_keys = NULL; /* key storage */
777 GMemChunk *giop_objkey_vals = NULL; /* val storage */
782 * ------------------------------------------------------------------------------------------+
783 * Private helper functions
784 * ------------------------------------------------------------------------------------------+
790 * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
793 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
794 GList * newlist_start;
795 comp_req_list_entry_t * entry = NULL;
798 entry = g_malloc(sizeof(comp_req_list_entry_t));
799 opn = g_strdup(op); /* duplicate operation for storage */
802 entry->reqid = reqid;
804 entry->operation = opn;
805 entry->repoid = NULL; /* dont have yet */
807 newlist_start = g_list_append (list, entry); /* append */
809 return newlist_start;
814 * Used to find an entry with matching Frame Number FN
815 * in the complete_request_list list.
818 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
820 GList * element; /* entry in list */
821 comp_req_list_entry_t * entry_ptr = NULL;
823 element = g_list_last(giop_complete_request_list); /* start from last */
825 while(element) { /* valid list entry */
826 entry_ptr = element->data; /* grab data pointer */
827 if (entry_ptr->fn == fn) { /* similar FN */
830 element = g_list_previous(element); /* try next previous */
833 return NULL; /* no match so return NULL */
838 * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
840 * Call this when you know a FN and matching giop_sub_handle_t and repoid
842 * This is done in say, try_explicit_dissector for example.
846 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
848 comp_req_list_entry_t * entry = NULL;
849 entry = find_fn_in_list(fn); /* grab FN data entry */
853 entry->repoid = g_strdup(repoid); /* copy and store */
861 /* giop_complete_reply_hash "EQUAL" Functions */
863 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
864 struct complete_reply_hash_key *mk1 = (struct complete_reply_hash_key *)v;
865 struct complete_reply_hash_key *mk2 = (struct complete_reply_hash_key *)w;
867 if (mk1->fn == mk2->fn) {
871 return 0; /* found differences */
874 /* giop_complete_reply_hash "HASH" Functions */
876 static guint32 complete_reply_hash_fn(gconstpointer v) {
877 guint32 val; /* init hash value */
878 struct complete_reply_hash_key *key = (struct complete_reply_hash_key *)v;
880 val = key->fn; /* simple and unique */
887 * Insert the FN and MFN together in our complete_reply_hash.
890 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
892 struct complete_reply_hash_key key, *new_key;
893 struct complete_reply_hash_val *val = NULL;
897 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
900 return; /* FN collision */
903 new_key = g_mem_chunk_alloc(giop_complete_reply_keys);
904 new_key->fn = fn; /* save FN */
906 val = g_mem_chunk_alloc(giop_complete_reply_vals);
907 val->mfn = mfn; /* and MFN */
909 g_hash_table_insert(giop_complete_reply_hash, new_key, val);
914 * Find the MFN values from a given FN key.
915 * Assumes the complete_reply_hash is already populated.
918 static guint32 get_mfn_from_fn(guint32 fn) {
920 struct complete_reply_hash_key key;
921 struct complete_reply_hash_val *val = NULL;
922 guint32 mfn = fn; /* save */
925 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
928 mfn = val->mfn; /* grab it */
931 return mfn; /* mfn or fn if not found */
936 * Attempt to find the MFN for this FN, and return it.
937 * Return MFN if found, or just FN if not. This is
938 * only used when we are building
941 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
943 GList * element; /* last entry in list */
944 comp_req_list_entry_t * entry_ptr = NULL;
946 /* Need Some pretty snappy code */
948 /* Loop back from current end of complete_request_list looking for */
949 /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
952 * As this routine is only called during initial pass of data,
953 * and NOT when a user clicks, it is ok to start from Current
954 * end of complete_request_list when searching for a match.
955 * As that list is bing populated in the same order as FN's
958 * Also, can make check for same reqid more detailed, but I start
959 * with reqid. Could add say port or address checks etc later ??
963 element = g_list_last(giop_complete_request_list); /* get last */
965 while(element) { /* valid list entry */
966 entry_ptr = element->data; /* grab data pointer */
967 if (entry_ptr->reqid == reqid) { /* similar reqid */
968 return entry_ptr->fn; /* return MFN */
970 element = g_list_previous(element); /* try next previous */
973 return fn; /* no match so return FN */
977 /* Module Hash "EQUAL" Functions */
979 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
980 struct giop_module_key *mk1 = (struct giop_module_key *)v;
981 struct giop_module_key *mk2 = (struct giop_module_key *)w;
983 if (!strcmp(mk1->module, mk2->module)) {
987 return 0; /* found differences */
990 /* Module Hash "HASH" Functions */
992 static guint32 giop_hash_module_hash(gconstpointer v) {
995 guint32 val = 0; /* init hash value */
997 struct giop_module_key *key = (struct giop_module_key *)v;
1000 * Hmm, try this simple hashing scheme for now.
1001 * ie: Simple summation, FIX later -- FS
1006 len = strlen(key->module);
1008 for (i=0; i<len; i++) {
1009 val += (guint8) key->module[i];
1018 * ------------------------------------------------------------------------------------------+
1019 * Public Utility functions
1020 * ------------------------------------------------------------------------------------------+
1027 * Routine to allow giop users to register their sub dissector function, name, and
1028 * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1029 * value returned from their proto_register_protocol(), so we can enable/disbale it
1030 * through the GUI (edit protocols).
1032 * This is used by try_explicit_giop_dissector() to find the
1033 * correct sub-dissector.
1037 void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
1039 struct giop_module_key module_key, *new_module_key;
1040 struct giop_module_val *module_val = NULL;
1042 module_key.module = module; /* module name */
1044 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1047 return; /* module name collision */
1050 /* So, passed module name should NOT exist in hash at this point.*/
1053 printf("giop:register_module: Adding Module %s to module hash \n", module);
1054 printf("giop:register_module: Module sub dissector name is %s \n", name);
1057 new_module_key = g_mem_chunk_alloc(giop_module_keys);
1058 new_module_key->module = module; /* save Module or interface name from IDL */
1060 module_val = g_mem_chunk_alloc(giop_module_vals);
1062 module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
1064 module_val->subh->sub_name = name; /* save dissector name */
1065 module_val->subh->sub_fn = sub; /* save subdissector*/
1066 module_val->subh->sub_proto = sub_proto; /* save subdissector's proto_XXX value */
1068 g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1075 /* Object Key Hash "EQUAL" Functions */
1077 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1078 struct giop_object_key *v1 = (struct giop_object_key *)v;
1079 struct giop_object_key *v2 = (struct giop_object_key *)w;
1081 if (v1->objkey_len != v2->objkey_len)
1082 return 0; /* no match because different length */
1084 /* Now do a byte comaprison */
1086 if (!memcmp(v1->objkey,v2->objkey, v1->objkey_len)) {
1087 return 1; /* compares ok */
1091 printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1094 return 0; /* found differences */
1097 /* Object Key Hash "HASH" Functions */
1099 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1100 struct giop_object_key *key = (struct giop_object_key *)v;
1103 guint32 val = 0; /* init hash value */
1107 * Hmm, try this simple hashing scheme for now.
1108 * ie: Simple summation
1114 printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1117 for (i=0; i< key->objkey_len; i++) {
1118 val += (guint8) key->objkey[i];
1126 * Routine to take an object key octet sequence, and length, and ptr to
1127 * a (null terminated )repository ID string, and store them in the obect key hash.
1129 * Blindly Inserts even if it does exist, See TODO at top for reason.
1132 static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
1134 struct giop_object_key objkey_key, *new_objkey_key;
1135 struct giop_object_val *objkey_val = NULL;
1137 objkey_key.objkey_len = len; /* length */
1138 objkey_key.objkey = obj; /* object key octet sequence */
1140 /* Look it up to see if it exists */
1142 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1144 /* CHANGED -- Same reqid, so abandon old entry */
1147 g_hash_table_remove(hash, &objkey_key);
1150 /* So, passed key should NOT exist in hash at this point.*/
1152 new_objkey_key = g_mem_chunk_alloc(giop_objkey_keys);
1153 new_objkey_key->objkey_len = len; /* save it */
1154 new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */
1156 objkey_val = g_mem_chunk_alloc(giop_objkey_vals);
1157 objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
1158 objkey_val->src = src; /* where IOR came from */
1162 printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
1163 objkey_val->repo_id, new_objkey_key->objkey_len);
1166 g_hash_table_insert(hash, new_objkey_key, objkey_val);
1173 * convert an ascii char representing a hex value,
1174 * to a numeric value.
1176 * returns value, or -1 if problem.
1180 static gint8 hex_char_to_val(guchar c){
1187 retval = c - 48; /* convert digit */
1191 c = toupper(c); /* convert to uppercase */
1192 if (c >= 'A' && c <= 'F') {
1203 * Convert from stringified IOR of the kind IOR:af4f7e459f....
1204 * to an IOR octet sequence.
1206 * User must free buffer.
1208 * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1209 * grab repoid etc for our objkey hash.
1213 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1216 gint8 tmpval; /* complete value */
1219 *out = g_new0(guint8, in_len); /* allocate buffer */
1225 /* skip past IOR: and convert character pairs to guint8 */
1227 for (i=4; i<in_len-1; i+=2) {
1228 if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1230 if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1231 g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1235 if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1236 g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1239 tmpval = tmpval_msb << 4;
1240 tmpval += tmpval_lsb;
1241 (*out)[(i-4)/2] = (guint8) tmpval;
1251 return (i-4)/2; /* length */
1258 * Simple getline, copied from somewhere :)
1262 static int getline(FILE *fp, gchar *line, int maxlen) {
1264 if (fgets(line,maxlen,fp) == NULL)
1267 return strlen(line);
1273 * Read a list of stringified IOR's from a named file, convert to IOR's
1274 * and store in object key hash
1277 static void read_IOR_strings_from_file(gchar *name, int max_iorlen) {
1278 guchar *buf; /* NOTE reused for every line */
1280 int ior_val_len; /* length after unstringifying. */
1282 guint8 *out; /* ptr to unstringified IOR */
1283 tvbuff_t *tvb; /* temp tvbuff for dissectin IORs */
1284 guint32 my_offset = 0;
1285 gboolean stream_is_big_endian;
1288 fp = fopen(name,"r"); /* open read only */
1291 if (errno == EACCES)
1292 fprintf(stderr, "Error opening file IOR.txt for reading: %s\n",strerror(errno));
1296 buf = g_malloc0(max_iorlen+1); /* input buf */
1298 while ((len = getline(fp,buf,max_iorlen+1)) > 0) {
1299 my_offset = 0; /* reset for every IOR read */
1301 ior_val_len = string_to_IOR(buf,len,&out); /* convert */
1305 /* Combination of tvb_new() and tvb_set_real_data().
1306 Can throw ReportedBoundsError.
1308 XXX - can it throw an exception in this case? If so, we
1309 need to catch it and clean up, but we really shouldn't allow
1310 it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
1313 tvb = tvb_new_real_data(out, ior_val_len, ior_val_len);
1315 stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1316 decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1326 fclose(fp); /* be nice */
1334 * Init routine, setup our request hash stuff, or delete old ref's
1336 * Cannot setup the module hash here as my init() may not be called before
1337 * users start registering. So I will move the module_hash stuff to
1338 * proto_register_giop, as is done with packet-rpc
1342 * Also, setup our objectkey/repoid hash here.
1346 static void giop_init(void) {
1350 * Create objkey/repoid hash, use my "equal" and "hash" functions.
1354 if (giop_objkey_hash)
1355 g_hash_table_destroy(giop_objkey_hash);
1356 if (giop_objkey_keys)
1357 g_mem_chunk_destroy(giop_objkey_keys);
1358 if (giop_objkey_vals)
1359 g_mem_chunk_destroy(giop_objkey_vals);
1363 * Create hash, use my "equal" and "hash" functions.
1367 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1369 giop_objkey_keys = g_mem_chunk_new("giop_objkey_keys",
1370 sizeof(struct giop_object_key),
1371 giop_objkey_init_count * sizeof(struct giop_object_key),
1374 giop_objkey_vals = g_mem_chunk_new("giop_objkey_vals",
1375 sizeof(struct giop_object_val),
1376 giop_objkey_init_count * sizeof(struct giop_object_val),
1381 * Create complete_reply_hash, use my "equal" and "hash" functions.
1385 if (giop_complete_reply_hash)
1386 g_hash_table_destroy(giop_complete_reply_hash);
1387 if (giop_complete_reply_keys)
1388 g_mem_chunk_destroy(giop_complete_reply_keys);
1389 if (giop_complete_reply_vals)
1390 g_mem_chunk_destroy(giop_complete_reply_vals);
1394 * Create hash, use my "equal" and "hash" functions.
1398 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1400 giop_complete_reply_keys = g_mem_chunk_new("giop_complete_reply_keys",
1401 sizeof(struct complete_reply_hash_key),
1402 complete_reply_hash_count * sizeof(struct complete_reply_hash_key),
1405 giop_complete_reply_vals = g_mem_chunk_new("giop_complete_reply_vals",
1406 sizeof(struct complete_reply_hash_val),
1407 complete_reply_hash_count * sizeof(struct complete_reply_hash_val),
1412 read_IOR_strings_from_file("IOR.txt", 600); /* testing */
1419 * Insert an entry in the GIOP Heuristic User table.
1421 * Uses giop_sub_handle_t to wrap giop user info.
1425 void register_giop_user(giop_sub_dissector_t *sub, gchar *name, int sub_proto) {
1427 giop_sub_handle_t *subh;
1429 subh = g_malloc(sizeof (giop_sub_handle_t));
1431 subh->sub_name = name;
1433 subh->sub_proto = sub_proto; /* proto_XXX from sub dissectors's proto_register_protocol() */
1435 giop_sub_list = g_slist_append (giop_sub_list, subh);
1441 * Lookup an object key in our object key hash, and return the corresponding
1446 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1448 struct giop_object_key objkey_key;
1449 struct giop_object_val *objkey_val = NULL;
1451 objkey_key.objkey_len = len; /* length */
1452 objkey_key.objkey = obj; /* object key octet sequence */
1454 /* Look it up to see if it exists */
1456 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1460 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1462 return objkey_val->repo_id; /* found */
1466 printf("FAILED Lookup of object key \n" );
1469 return NULL; /* not found */
1475 * Extract top level module/interface from repoid
1477 * eg from - "IDL:Echo/interface1:1.0"
1480 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1481 * get linux.org/Penguin/Teeth
1484 * User must free returned ptr after use.
1486 * TODO -- generalize for other Repoid encodings
1489 static gchar * get_modname_from_repoid(gchar *repoid) {
1491 gchar *modname = NULL;
1492 gchar *saved_repoid = NULL;
1494 guint8 stop_mod; /* Index of last character of modname in Repoid */
1495 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1498 saved_repoid = g_strdup(repoid); /* make a copy */
1500 /* Must start with IDL: , otherwise I get confused */
1502 if (g_strncasecmp("IDL:",repoid,4))
1505 /* Looks like a RepoID to me, so get Module or interface name */
1507 /* TODO -- put some code here to get Module name */
1509 for(i=4; c != '\0'; i++) {
1511 stop_mod = i; /* save */
1512 if (c == ':' ) /* delimiters */
1517 /* Now create a new string based on start and stop and \0 */
1519 modname = g_strndup(repoid+4, stop_mod - start_mod);
1534 * Display a "module" hash entry
1537 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1539 struct giop_module_val *mv = (struct giop_module_val *) val;
1540 struct giop_module_key *mk = (struct giop_module_key *) key;
1542 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1549 * Display a "complete_reply " hash entry
1552 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1554 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1555 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1557 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1565 * Display an "objkey" hash entry
1568 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1570 struct giop_object_val *mv = (struct giop_object_val *) val;
1571 struct giop_object_key *mk = (struct giop_object_key *) key;
1574 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1576 for (i=0; i<mk->objkey_len; i++) {
1577 printf("%.2x ", mk->objkey[i]);
1581 * If read from file, mark it as such..
1585 printf(", Repo ID = %s \n", mv->repo_id);
1588 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1596 * Display all giop_sub_list (GSList) entries
1599 static void display_heuristic_user_list() {
1602 giop_sub_handle_t *subh; /* handle */
1604 /* Get length of list */
1605 len = g_slist_length(giop_sub_list); /* find length */
1610 for (i=0; i<len; i++) {
1611 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1612 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1618 * Display all complete_request_list (GList) entries
1621 static void display_complete_request_list() {
1624 comp_req_list_entry_t *entry;
1626 /* Get length of list */
1627 len = g_list_length(giop_complete_request_list); /* find length */
1632 for (i=0; i<len; i++) {
1633 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1634 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1635 entry->reqid,entry->operation, entry->repoid);
1643 /* Dump Hash/List contents
1645 * collection_type specifies the list or hash to dump
1649 static void giop_dump_collection(collection_data_t collection_type) {
1651 switch(collection_type) {
1652 case cd_heuristic_users:
1653 printf("+----------------------------------------------+ \n");
1654 printf("+-------------- Heuristic User (Begin) --------+ \n");
1655 printf("+----------------------------------------------+ \n");
1657 display_heuristic_user_list();
1659 printf("+----------------------------------------------+ \n");
1660 printf("+-------------- Heuristic User (End) ----------+ \n");
1661 printf("+----------------------------------------------+ \n");
1665 case cd_complete_request_list:
1666 printf("+----------------------------------------------+ \n");
1667 printf("+------------- Complete Request List (Begin) --+ \n");
1668 printf("+----------------------------------------------+ \n");
1670 display_complete_request_list();
1672 printf("+----------------------------------------------+ \n");
1673 printf("+------------ Complete Request List (End) -----+ \n");
1674 printf("+----------------------------------------------+ \n");
1678 case cd_module_hash:
1679 printf("+----------------------------------------------+ \n");
1680 printf("+-------------- Module (Begin) ----------------+ \n");
1681 printf("+----------------------------------------------+ \n");
1683 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1685 printf("+----------------------------------------------+ \n");
1686 printf("+-------------- Module ( End) -----------------+ \n");
1687 printf("+----------------------------------------------+ \n\n");
1691 case cd_objkey_hash:
1692 printf("+----------------------------------------------+ \n");
1693 printf("+-------------- Objkey (Begin) ----------------+ \n");
1694 printf("+----------------------------------------------+ \n");
1696 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1698 printf("+----------------------------------------------+ \n");
1699 printf("+-------------- Objkey (End) ------------------+ \n");
1700 printf("+----------------------------------------------+ \n\n");
1704 case cd_complete_reply_hash:
1705 printf("+----------------------------------------------+ \n");
1706 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1707 printf("+----------------------------------------------+ \n");
1709 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1711 printf("+----------------------------------------------+ \n");
1712 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1713 printf("+----------------------------------------------+ \n");
1719 printf("giop: giop_dump_collection: Unknown type \n");
1730 * Loop through all subdissectors, and call them until someone
1731 * answers (returns TRUE). This function then returns TRUE, otherwise
1734 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1737 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1738 MessageHeader *header, gchar *operation ) {
1741 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1742 giop_sub_handle_t *subh = NULL;
1743 const char *saved_proto;
1745 len = g_slist_length(giop_sub_list); /* find length */
1750 saved_proto = pinfo->current_proto;
1751 for (i=0; i<len; i++) {
1752 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1754 if (proto_is_protocol_enabled(subh->sub_proto)) {
1755 pinfo->current_proto =
1756 proto_get_protocol_short_name(subh->sub_proto);
1757 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1759 pinfo->current_proto = saved_proto;
1760 return TRUE; /* found one, lets return */
1762 } /* protocol_is_enabled */
1765 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1766 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
1768 pinfo->current_proto = saved_proto;
1769 return res; /* result */
1775 * Find the matching repoid in the module hash and call
1776 * the dissector function if offset exists.
1779 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1780 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
1786 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1787 MessageHeader *header, gchar *operation, gchar *repoid ) {
1789 giop_sub_handle_t *subdiss = NULL; /* handle */
1790 gboolean res = FALSE;
1791 gchar *modname = NULL;
1792 struct giop_module_key module_key;
1793 struct giop_module_val *module_val = NULL;
1794 const char *saved_proto;
1798 * Get top level module/interface from complete repoid
1801 modname = get_modname_from_repoid(repoid);
1802 if (modname == NULL) {
1803 return res; /* unknown module name */
1807 /* Search for Module or interface name */
1809 module_key.module = modname; /* module name */
1810 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1812 if (module_val == NULL) {
1813 return res; /* module not registered */
1816 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1819 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1820 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1821 /* but only if user not clicking */
1823 if (!pinfo->fd->flags.visited)
1824 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1827 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1829 if (tvb_offset_exists(tvb, *offset)) {
1831 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
1834 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1836 saved_proto = pinfo->current_proto;
1837 pinfo->current_proto =
1838 proto_get_protocol_short_name(subdiss->sub_proto);
1839 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1840 pinfo->current_proto = saved_proto;
1842 } /* protocol_is_enabled */
1843 } /* offset exists */
1846 return res; /* return result */
1851 /* Take in an array of char and create a new string.
1852 * Replace non-printable characters with periods.
1854 * The array may contain \0's so dont use strdup
1855 * The string is \0 terminated, and thus longer than
1856 * the initial sequence.
1857 * Caller must free the new string.
1860 static gchar * make_printable_string (gchar *in, guint32 len) {
1862 gchar *print_string = NULL;
1864 print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1865 memcpy(print_string, in, len); /* and make a copy of input data */
1867 for(i=0; i < len; i++) {
1868 if( !isprint( (unsigned char)print_string[i] ) )
1869 print_string[i] = '.';
1872 return print_string; /* return ptr */
1875 /* Determine the byte order from the GIOP MessageHeader */
1877 gboolean is_big_endian (MessageHeader * header) {
1878 gboolean big_endian = FALSE;
1880 switch (header->GIOP_version.minor) {
1883 if (header->flags & 0x01)
1903 * Calculate new offset, based on the current offset, and user supplied
1904 * "offset delta" value, and the alignment requirement.
1908 * eg: Used for GIOP 1.2 where Request and Reply bodies are
1909 * aligned on 8 byte boundaries.
1912 static void set_new_alignment(int *offset, int delta, int alignment) {
1914 while( ( (*offset + delta) % alignment) != 0)
1923 * ------------------------------------------------------------------------------------------+
1924 * Public get_CDR_xxx functions.
1925 * ------------------------------------------------------------------------------------------+
1931 * Gets data of type any. This is encoded as a TypeCode
1932 * followed by the encoded value.
1935 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
1936 gboolean stream_is_big_endian, int boundary,
1937 MessageHeader * header ) {
1939 guint32 TCKind; /* TypeCode */
1941 /* get TypeCode of any */
1942 TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1944 /* dissect data of type TCKind */
1945 dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1949 /* Copy a 1 octet sequence from the tvbuff
1950 * which represents a boolean value, and convert
1951 * it to a boolean value.
1952 * Offset is then incremented by 1, to indicate the 1 octet which
1953 * has been processed.
1956 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1959 val = tvb_get_guint8(tvb, *offset); /* easy */
1964 /* Copy a 1 octet sequence from the tvbuff
1965 * which represents a char, and convert
1966 * it to an char value.
1967 * offset is then incremented by 1, to indicate the 1 octet which
1968 * has been processed.
1971 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1974 val = tvb_get_guint8(tvb, *offset); /* easy */
1982 * Floating Point Data Type double IEEE 754-1985
1984 * Copy an 8 octet sequence from the tvbuff
1985 * which represents a double value, and convert
1986 * it to a double value, taking into account byte order.
1987 * offset is first incremented so that it falls on a proper alignment
1988 * boundary for double values.
1989 * offset is then incremented by 8, to indicate the 8 octets which
1990 * have been processed.
1993 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1997 /* double values must be aligned on a 8 byte boundary */
1999 while( ( (*offset + boundary) % 8) != 0)
2002 val = (stream_is_big_endian) ? tvb_get_ntohieee_double (tvb, *offset) :
2003 tvb_get_letohieee_double (tvb, *offset);
2011 /* Copy a 4 octet sequence from the tvbuff
2012 * which represents an enum value, and convert
2013 * it to an enum value, taking into account byte order.
2014 * offset is first incremented so that it falls on a proper alignment
2015 * boundary for an enum (4)
2016 * offset is then incremented by 4, to indicate the 4 octets which
2017 * have been processed.
2019 * Enum values are encoded as unsigned long.
2023 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2025 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2031 * Copy an octet sequence from the tvbuff
2032 * which represents a Fixed point decimal type, and create a string representing
2033 * a Fixed point decimal type. There are no alignment restrictions.
2034 * Size and scale of fixed decimal type is determined by IDL.
2036 * digits - IDL specified number of "digits" for this fixed type
2037 * scale - IDL specified "scale" for this fixed type
2040 * eg: typedef fixed <5,2> fixed_t;
2041 * could represent numbers like 123.45, 789.12,
2044 * As the fixed type could be any size, I will not try to fit it into our
2045 * simple types like gdouble or glong etc. I will just create a string buffer holding
2046 * a representation (after scale is applied), and with a decimal point or zero padding
2047 * inserted at the right place if necessary. The string is null terminated
2049 * so string may look like
2052 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2054 * According to spec, digits <= 31
2055 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2058 * User must remember to free the buffer
2063 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2065 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2066 guint32 i ; /* loop */
2067 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2068 /* this does not include sign, decimal point and \0 */
2069 guint32 sindex = 0; /* string index */
2070 gchar *tmpbuf; /* temp buff, holds string without scaling */
2071 guint8 tval; /* temp val storage */
2074 * how many bytes to hold digits and scale (if scale <0)
2076 * eg: fixed <5,2> = 5 digits
2077 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2081 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2085 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2087 slen = digits; /* digits */
2091 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2094 tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
2097 * Register a cleanup function in case on of our tvbuff accesses
2098 * throws an exception. We need to clean up tmpbuf.
2100 CLEANUP_PUSH(g_free, tmpbuf);
2102 /* If even , grab 1st dig */
2104 if (!(digits & 0x01)) {
2105 tval = get_CDR_octet(tvb,offset);
2107 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2109 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2114 * Loop, but stop BEFORE we hit last digit and sign
2115 * if digits = 1 or 2, then this part is skipped
2119 for(i=0; i< ((digits-1)/2 ); i++) {
2120 tval = get_CDR_octet(tvb,offset);
2122 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2125 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2127 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2134 printf("giop:get_CDR_fixed(): before last digit \n");
2138 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2140 tval = get_CDR_octet(tvb,offset);
2142 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2144 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2147 sign = tval & 0x0f; /* get sign */
2149 /* So now, we have all digits in an array, and the sign byte
2150 * so lets generate a printable string, taking into account the scale
2154 sindex = 0; /* reset */
2155 *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
2156 * \0 -- TODO check slen is reasonable first */
2158 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
2163 (*seq)[sindex] = '+'; /* put sign in first string position */
2166 (*seq)[sindex] = '-';
2169 g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2170 (*seq)[sindex] = '*'; /* flag as sign unkown */
2176 /* Add decimal point or padding 0's, depending if scale is positive or
2177 * negative, respectively
2181 for (i=0; i<digits-scale; i++) {
2182 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
2186 (*seq)[sindex] = '.'; /* decimal point */
2189 for (i=digits-scale; i<digits; i++) {
2190 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
2194 (*seq)[sindex] = '\0'; /* string terminator */
2198 /* negative scale, dump digits and pad out with 0's */
2200 for (i=0; i<digits-scale; i++) {
2202 (*seq)[sindex] = tmpbuf[i]; /* save digits */
2204 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
2209 (*seq)[sindex] = '\0'; /* string terminator */
2214 * We're done with tmpbuf, so we can call the cleanup handler to free
2215 * it, and then pop the cleanup handler.
2217 CLEANUP_CALL_AND_POP;
2220 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2230 * Floating Point Data Type float IEEE 754-1985
2232 * Copy an 4 octet sequence from the tvbuff
2233 * which represents a float value, and convert
2234 * it to a float value, taking into account byte order.
2235 * offset is first incremented so that it falls on a proper alignment
2236 * boundary for float values.
2237 * offset is then incremented by 4, to indicate the 4 octets which
2238 * have been processed.
2241 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2245 /* float values must be aligned on a 4 byte boundary */
2247 while( ( (*offset + boundary) % 4) != 0)
2250 val = (stream_is_big_endian) ? tvb_get_ntohieee_float (tvb, *offset) :
2251 tvb_get_letohieee_float (tvb, *offset);
2260 * Decode an Interface type, and display it on the tree.
2263 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2264 gboolean stream_is_big_endian, int boundary) {
2267 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2273 /* Copy a 4 octet sequence from the tvbuff
2274 * which represents a signed long value, and convert
2275 * it to an signed long vaule, taking into account byte order.
2276 * offset is first incremented so that it falls on a proper alignment
2277 * boundary for long values.
2278 * offset is then incremented by 4, to indicate the 4 octets which
2279 * have been processed.
2282 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2286 /* unsigned long values must be aligned on a 4 byte boundary */
2287 while( ( (*offset + boundary) % 4) != 0)
2290 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2291 tvb_get_letohl (tvb, *offset);
2298 * Decode an Object type, and display it on the tree.
2301 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2302 gboolean stream_is_big_endian, int boundary) {
2304 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2310 /* Copy a 1 octet sequence from the tvbuff
2311 * which represents a octet, and convert
2312 * it to an octet value.
2313 * offset is then incremented by 1, to indicate the 1 octet which
2314 * has been processed.
2317 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2320 val = tvb_get_guint8(tvb, *offset); /* easy */
2326 /* Copy a sequence of octets from the tvbuff.
2327 * Caller of this function must remember to free the
2328 * array pointed to by seq.
2329 * This function also increments offset by len.
2332 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, int len) {
2334 if (! tvb_bytes_exist(tvb, *offset,len)) {
2336 * Generate an exception, and stop processing.
2337 * We do that now, rather than after allocating the buffer, so we
2338 * don't have to worry about freeing the buffer.
2339 * XXX - would we be better off using a cleanup routine?
2341 tvb_get_guint8(tvb, *offset + len);
2345 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2346 * do what we do now, and null-terminate the string (which also means
2347 * we don't need to zero out the entire allocation, just the last byte)?
2349 *seq = g_new0(gchar, len + 1);
2350 tvb_memcpy( tvb, *seq, *offset, len);
2355 /* Copy a 2 octet sequence from the tvbuff
2356 * which represents a signed short value, and convert
2357 * it to a signed short value, taking into account byte order.
2358 * offset is first incremented so that it falls on a proper alignment
2359 * boundary for short values.
2360 * offset is then incremented by 2, to indicate the 2 octets which
2361 * have been processed.
2364 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2368 /* short values must be aligned on a 2 byte boundary */
2369 while( ( (*offset + boundary) % 2) != 0)
2372 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2373 tvb_get_letohs (tvb, *offset);
2381 /* Copy an octet sequence from the tvbuff
2382 * which represents a string, and convert
2383 * it to an string value, taking into account byte order.
2384 * offset is first incremented so that it falls on a proper alignment
2385 * boundary for string values. (begins with an unsigned long LI)
2387 * String sequence is copied to a buffer "seq". This must
2388 * be freed by the calling program.
2389 * offset is then incremented, to indicate the octets which
2390 * have been processed.
2392 * returns number of octets in the sequence
2394 * Note: This function only supports single byte encoding at the
2395 * moment until I get a handle on multibyte encoding etc.
2400 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2405 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2408 (*offset)++; /* must step past \0 delimiter */
2412 get_CDR_octet_seq(tvb, seq, offset, slength);
2414 *seq = g_strdup(""); /* zero-length string */
2417 return slength; /* return length */
2421 /* Process a sequence of octets that represent the
2422 * Pseudo Object Type "TypeCode". Typecodes are used for example,
2424 * This function also increments offset to the correct position.
2426 * It will parse the TypeCode and output data to the "tree" provided
2429 * It returns a guint32 representing a TCKind value.
2432 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2433 gboolean stream_is_big_endian, int boundary,
2434 MessageHeader * header ) {
2437 gint16 s_octet2; /* signed int16 */
2438 guint16 u_octet2; /* unsigned int16 */
2439 guint32 u_octet4; /* unsigned int32 */
2441 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2443 proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2444 *offset-sizeof(val),4,val);
2447 /* Grab the data according to Typecode Table - Corba Chapter 15 */
2450 case tk_null: /* empty parameter list */
2452 case tk_void: /* empty parameter list */
2454 case tk_short: /* empty parameter list */
2456 case tk_long: /* empty parameter list */
2458 case tk_ushort: /* empty parameter list */
2460 case tk_ulong: /* empty parameter list */
2462 case tk_float: /* empty parameter list */
2464 case tk_double: /* empty parameter list */
2466 case tk_boolean: /* empty parameter list */
2468 case tk_char: /* empty parameter list */
2470 case tk_octet: /* empty parameter list */
2472 case tk_any: /* empty parameter list */
2474 case tk_TypeCode: /* empty parameter list */
2476 case tk_Principal: /* empty parameter list */
2478 case tk_objref: /* complex parameter list */
2479 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2481 case tk_struct: /* complex parameter list */
2482 dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2484 case tk_union: /* complex parameter list */
2485 dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2487 case tk_enum: /* complex parameter list */
2488 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2491 case tk_string: /* simple parameter list */
2492 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2494 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2495 *offset-sizeof(u_octet4),4,u_octet4);
2499 case tk_sequence: /* complex parameter list */
2500 dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2502 case tk_array: /* complex parameter list */
2503 dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2505 case tk_alias: /* complex parameter list */
2506 dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2508 case tk_except: /* complex parameter list */
2509 dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2511 case tk_longlong: /* empty parameter list */
2513 case tk_ulonglong: /* empty parameter list */
2515 case tk_longdouble: /* empty parameter list */
2517 case tk_wchar: /* empty parameter list */
2519 case tk_wstring: /* simple parameter list */
2520 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2522 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2523 *offset-sizeof(u_octet4),4,u_octet4);
2527 case tk_fixed: /* simple parameter list */
2528 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2530 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2531 *offset-sizeof(u_octet2),2,u_octet2);
2534 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2536 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2537 *offset-sizeof(s_octet2),2,s_octet2);
2541 case tk_value: /* complex parameter list */
2542 dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2544 case tk_value_box: /* complex parameter list */
2545 dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2547 case tk_native: /* complex parameter list */
2548 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2550 case tk_abstract_interface: /* complex parameter list */
2551 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2554 g_warning("giop: Unknown TCKind %u \n", val);
2563 /* Copy a 4 octet sequence from the tvbuff
2564 * which represents an unsigned long value, and convert
2565 * it to an unsigned long vaule, taking into account byte order.
2566 * offset is first incremented so that it falls on a proper alignment
2567 * boundary for unsigned long values.
2568 * offset is then incremented by 4, to indicate the 4 octets which
2569 * have been processed.
2572 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2576 /* unsigned long values must be aligned on a 4 byte boundary */
2577 while( ( (*offset + boundary) % 4) != 0)
2580 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2581 tvb_get_letohl (tvb, *offset);
2588 /* Copy a 2 octet sequence from the tvbuff
2589 * which represents an unsigned short value, and convert
2590 * it to an unsigned short value, taking into account byte order.
2591 * offset is first incremented so that it falls on a proper alignment
2592 * boundary for unsigned short values.
2593 * offset is then incremented by 2, to indicate the 2 octets which
2594 * have been processed.
2597 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2601 /* unsigned short values must be aligned on a 2 byte boundary */
2602 while( ( (*offset + boundary) % 2) != 0)
2605 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2606 tvb_get_letohs (tvb, *offset);
2614 /* Copy a wchar from the tvbuff.
2615 * Caller of this function must remember to free the
2616 * array pointed to by seq.
2617 * This function also increments offset according to
2620 * For GIOP 1.1 read 2 octets and return size -2. The
2621 * negation means there is no size element in the packet
2622 * and therefore no size to add to the tree.
2624 * For GIOP 1.2 read size of wchar and the size
2625 * octets. size is returned as a gint8.
2627 * For both GIOP versions the wchar is returned
2628 * as a printable string.
2632 /* NOTE: This is very primitive in that it just reads
2633 * the wchar as a series of octets and returns them
2634 * to the user. No translation is attempted based on
2635 * byte orientation, nor on code set. I.e it only
2636 * really reads past the wchar and sets the offset
2640 /* The "decoding" is done according to CORBA chapter 15.
2641 * Wchar is not supported for GIOP 1.0.
2644 gint8 get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2649 /* CORBA chapter 15:
2650 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
2651 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
2652 * followed by the elements of the octet sequence representing
2653 * the encoded value of the wchar.
2656 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2657 slength = 2; /* set for GIOP 1.1 length in octets */
2659 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2660 slength = get_CDR_octet(tvb,offset);
2663 /* ??? assume alignment is ok for GIOP 1.1 ??? */
2664 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2666 /* now turn octets (wchar) into something that can be printed by the user */
2667 *seq = make_printable_string(raw_wstring, slength);
2669 g_free(raw_wstring);
2672 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2673 if (header->GIOP_version.minor < 2)
2676 return slength; /* return length */
2681 /* Copy a wstring from the tvbuff.
2682 * Caller of this function must remember to free the
2683 * array pointed to by seq.
2684 * This function also increments offset, according to
2685 * wstring length. length is returned as guint32
2688 /* NOTE: This is very primitive in that it just reads
2689 * the wstring as a series of octets and returns them
2690 * to the user. No translation is attempted based on
2691 * byte orientation, nor on code set. I.e it only
2692 * really reads past the wstring and sets the offset
2696 /* The "decoding" is done according to CORBA chapter 15.
2697 * Wstring is not supported for GIOP 1.0.
2701 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
2702 int boundary, MessageHeader * header) {
2707 /* CORBA chapter 15:
2708 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
2709 * length and string are NUL terminated (length???).
2710 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2714 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2716 /* get length, same for all GIOP versions,
2717 * although for 1.2 CORBA doesnt say, so assume.
2719 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2723 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2724 slength = 5; /* better than core dumping during debug */
2728 if (header->GIOP_version.minor < 2) {
2730 (*offset)++; /* must step past \0 delimiter */
2732 /* assume length is number of characters and not octets, spec not clear */
2733 slength = slength * 2; /* length in octets is 2 * wstring length */
2737 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2739 /* now turn octets (wstring) into something that can be printed by the user */
2740 *seq = make_printable_string(raw_wstring, slength);
2742 g_free(raw_wstring);
2745 return slength; /* return length */
2752 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2754 * typedef short AddressingDisposition;
2755 * const short KeyAddr = 0;
2756 * const short ProfileAddr = 1;
2757 * const short ReferenceAddr = 2;
2758 * struct IORAddressingInfo {
2759 * unsigned long selected_profile_index;
2763 * union TargetAddress switch (AddressingDisposition) {
2764 * case KeyAddr: sequence <octet> object_key;
2765 * case ProfileAddr: IOP::TaggedProfile profile;
2766 * case ReferenceAddr: IORAddressingInfo ior;
2771 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
2772 MessageHeader * header, gboolean stream_is_big_endian)
2774 guint16 discriminant;
2776 gchar *p_object_key;
2780 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2783 proto_tree_add_text (tree, tvb, *offset -2, 2,
2784 "TargetAddress Discriminant: %u", discriminant);
2787 switch (discriminant)
2789 case 0: /* KeyAddr */
2790 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2793 proto_tree_add_text (tree, tvb, *offset -4, 4,
2794 "KeyAddr (object key length): %u", len);
2799 get_CDR_octet_seq(tvb, &object_key, offset, len);
2800 p_object_key = make_printable_string( object_key, len );
2804 proto_tree_add_text (tree, tvb, *offset -len, len,
2805 "KeyAddr (object key): %s", p_object_key);
2807 g_free( p_object_key );
2808 g_free( object_key );
2811 case 1: /* ProfileAddr */
2812 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2813 stream_is_big_endian, NULL);
2815 case 2: /* ReferenceAddr */
2816 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2820 proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2821 "ReferenceAddr (selected_profile_index): %u", u_octet4);
2824 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2832 dissect_reply_body (tvbuff_t *tvb, u_int offset, packet_info *pinfo,
2833 proto_tree *tree, gboolean stream_is_big_endian,
2834 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2836 u_int sequence_length;
2837 gboolean exres = FALSE; /* result of trying explicit dissectors */
2838 gchar * repoid = NULL; /* Repositor ID looked up from objkey */
2841 * comp_req_list stuff
2844 comp_req_list_entry_t * entry = NULL; /* data element in our list */
2848 switch (reply_status)
2850 case SYSTEM_EXCEPTION:
2852 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2855 case USER_EXCEPTION:
2857 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2861 proto_tree_add_text(tree, tvb, offset-4, 4,
2862 "Exception length: %u", sequence_length);
2864 if (sequence_length != 0)
2868 proto_tree_add_text(tree, tvb, offset, sequence_length,
2870 tvb_format_text(tvb, offset, sequence_length));
2874 header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2876 /* read exception id from buffer and store in*/
2878 tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2884 offset += sequence_length;
2890 * Now just fall through to the NO_EXCEPTION part
2891 * as this is common .
2899 /* lookup MFN in hash directly */
2901 mfn = get_mfn_from_fn(pinfo->fd->num);
2903 if (mfn == pinfo->fd->num)
2904 return; /* no matching frame number, what am I */
2906 /* get entry for this MFN */
2907 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2910 return; /* no matching entry */
2914 * If this packet is a REPLY to a RESOLVE(request)
2916 * TODO - make this lookup faster -- FS
2919 if (!strcmp(giop_op_resolve,entry->operation)) {
2920 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2924 /* TODO -- Put stuff here for other "interesting operations" */
2928 * Call sub dissector.
2929 * First try an find a explicit sub_dissector, then if that
2930 * fails, try the heuristic method.
2935 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
2938 /* Only call heuristic if no explicit dixxector was found */
2941 try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
2947 case LOCATION_FORWARD:
2948 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2952 case LOCATION_FORWARD_PERM:
2953 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2957 case NEEDS_ADDRESSING_MODE: {
2959 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2961 proto_tree_add_text (tree, tvb, offset -2, 2,
2962 "AddressingDisposition: %u", addr_disp);
2970 g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
2976 g_free(repoid); /* free resource */
2986 /* The format of the Reply Header for GIOP 1.0 and 1.1
2987 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
2989 struct ReplyHeader_1_0 {
2990 IOP::ServiceContextList service_context;
2991 unsigned long request_id;
2992 ReplyStatusType_1_0 reply_status;
2996 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
2997 proto_tree * clnp_tree, MessageHeader * header,
2998 gboolean stream_is_big_endian) {
3002 guint32 reply_status;
3003 proto_tree *reply_tree = NULL;
3005 guint32 mfn; /* matching frame number */
3008 tf = proto_tree_add_text (tree, tvb, offset, -1,
3009 "General Inter-ORB Protocol Reply");
3010 if (reply_tree == NULL)
3012 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3018 * Decode IOP::ServiceContextList
3021 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3023 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3025 if (check_col(pinfo->cinfo, COL_INFO)) {
3026 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3030 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3031 "Request id: %u", request_id);
3034 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3036 if (check_col(pinfo->cinfo, COL_INFO)) {
3037 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3038 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3043 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3045 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3050 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3053 if (! pinfo->fd->flags.visited) {
3054 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3055 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3056 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3060 header->req_id = request_id; /* save for sub dissector */
3061 header->rep_status = reply_status; /* save for sub dissector */
3063 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3064 reply_status, header,tree);
3069 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3070 * and 1.1 header, only the fields have been rearranged. From Section
3071 * 15.4.3.1 of the CORBA 2.4 specification:
3073 * struct ReplyHeader_1_2 {
3074 * unsigned long request_id;
3075 * ReplyStatusType_1_2 reply_status;
3076 * IOP:ServiceContextList service_context;
3080 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3081 proto_tree * tree, proto_tree * clnp_tree,
3082 MessageHeader * header,
3083 gboolean stream_is_big_endian) {
3087 guint32 reply_status;
3088 proto_tree *reply_tree = NULL;
3090 guint32 mfn; /* matching frame number */
3093 tf = proto_tree_add_text (tree, tvb, offset, -1,
3094 "General Inter-ORB Protocol Reply");
3095 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3098 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3100 if (check_col(pinfo->cinfo, COL_INFO)) {
3101 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3105 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3106 "Request id: %u", request_id);
3109 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3111 if (check_col(pinfo->cinfo, COL_INFO)) {
3112 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3113 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3118 proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3120 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3125 * Decode IOP::ServiceContextList
3128 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3131 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3134 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3137 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3140 if (! pinfo->fd->flags.visited) {
3141 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3142 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3143 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3148 * Add header to argument list so sub dissector can get header info.
3151 header->req_id = request_id; /* save for sub dissector */
3152 header->rep_status = reply_status; /* save for sub dissector */
3154 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3155 reply_status,header,tree);
3161 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3162 proto_tree * tree, proto_tree * clnp_tree,
3163 MessageHeader * header, gboolean stream_is_big_endian) {
3167 proto_tree *cancel_request_tree = NULL;
3171 tf = proto_tree_add_text (tree, tvb, offset, -1,
3172 "General Inter-ORB Protocol CancelRequest");
3173 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3176 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3178 if (check_col(pinfo->cinfo, COL_INFO)) {
3179 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3183 proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4,
3184 "Request id: %u", request_id);
3190 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
3191 * in section 15.4.2.1 of the CORBA 2.4 specification.
3193 * struct RequestHeader{
3194 * IOP::ServiceContextList service_context;
3195 * unsigned long request_id;
3196 * boolean response_expected;
3197 * octet reserved[3]; // Only in GIOP 1.1
3198 * sequence<octet> object_key;
3200 * CORBA::OctetSeq requesting_principal;
3204 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3205 proto_tree * tree, proto_tree * clnp_tree,
3206 MessageHeader * header, gboolean stream_is_big_endian)
3212 guint32 objkey_len = 0; /* object key length */
3213 gchar *objkey = NULL; /* object key sequence */
3214 gchar *print_objkey; /* printable object key sequence */
3215 gboolean exres = FALSE; /* result of trying explicit dissectors */
3218 gchar *requesting_principal;
3219 gchar *print_requesting_principal;
3220 guint8 response_expected;
3222 proto_tree *request_tree = NULL;
3225 gchar *repoid = NULL; /* from object key lookup in objkey hash */
3230 tf = proto_tree_add_text (tree, tvb, offset, -1,
3231 "General Inter-ORB Protocol Request");
3232 if (request_tree == NULL)
3234 request_tree = proto_item_add_subtree (tf, ett_giop_request);
3243 * Decode IOP::ServiceContextList
3246 decode_ServiceContextList(tvb, pinfo, request_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3249 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3250 if (check_col(pinfo->cinfo, COL_INFO))
3252 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3256 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3257 "Request id: %u", request_id);
3260 response_expected = tvb_get_guint8( tvb, offset );
3262 if (check_col(pinfo->cinfo, COL_INFO))
3264 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3265 response_expected ? "two-way" : "one-way");
3269 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3270 "Response expected: %u", response_expected);
3273 if( header->GIOP_version.minor > 0)
3275 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3278 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3279 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3286 /* Length of object_key sequence */
3287 objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3292 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3293 /**/ "Object Key length: %u", objkey_len);
3298 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3300 print_objkey = make_printable_string(objkey, objkey_len);
3304 proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
3305 /**/ "Object Key: %s", print_objkey);
3309 g_free( print_objkey );
3313 * Register a cleanup function in case on of our tvbuff accesses
3314 * throws an exception. We need to clean up objkey.
3316 CLEANUP_PUSH(g_free, objkey);
3318 /* length of operation string and string */
3319 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3322 proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3323 /**/ "Operation length: %u", len);
3328 if (check_col(pinfo->cinfo, COL_INFO))
3330 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3334 proto_tree_add_text (request_tree, tvb, offset - len, len,
3335 /**/ "Operation: %s", operation);
3341 * Register a cleanup function in case on of our tvbuff accesses
3342 * throws an exception. We need to clean up operation.
3344 CLEANUP_PUSH(g_free, operation);
3346 /* length of requesting_principal string */
3347 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3350 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3351 /**/ "Requesting Principal Length: %u", len);
3356 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3358 print_requesting_principal = make_printable_string(requesting_principal, len);
3362 proto_tree_add_text (request_tree, tvb, offset - len, len,
3363 /**/ "Requesting Principal: %s", print_requesting_principal);
3367 g_free( print_requesting_principal );
3368 g_free( requesting_principal );
3373 * Save FN,reqid,and operation for later. Add sub_handle later.
3374 * But only if user is NOT clicking.
3377 if (! pinfo->fd->flags.visited)
3378 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3379 request_id,operation,NULL);
3383 * Call subdissector here before freeing "operation" and "key"
3384 * pass request_id also.
3385 * First try an find an explicit sub_dissector, then if that
3386 * fails, try the heuristic method.
3391 header->req_id = request_id; /* save for sub dissector */
3392 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3396 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3399 /* Only call heuristic if no explicit dissector was found */
3402 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3407 * We're done with operation, so we can call the cleanup handler to free
3408 * it, and then pop the cleanup handler.
3410 CLEANUP_CALL_AND_POP;
3413 * We're done with objkey, so we can call the cleanup handler to free
3414 * it, and then pop the cleanup handler.
3416 CLEANUP_CALL_AND_POP;
3420 /** The format of a GIOP 1.2 RequestHeader message is
3421 * (CORBA 2.4, sec. 15.4.2):
3423 * struct RequestHeader_1_2 {
3424 * unsigned long request_id;
3425 * octet response_flags;
3426 * octet reserved[3];
3427 * TargetAddress target;
3429 * IOP::ServiceContextList service_context;
3430 * // requesting_principal not in GIOP 1.2
3434 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3435 proto_tree * tree, proto_tree * clnp_tree,
3436 MessageHeader * header, gboolean stream_is_big_endian)
3441 guint8 response_flags;
3443 gchar *operation = NULL;
3444 proto_tree *request_tree = NULL;
3446 gboolean exres = FALSE; /* result of trying explicit dissectors */
3448 gchar *repoid = NULL;
3453 tf = proto_tree_add_text (tree, tvb, offset, -1,
3454 "General Inter-ORB Protocol Request");
3455 request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3458 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3459 if (check_col(pinfo->cinfo, COL_INFO))
3461 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3465 proto_tree_add_text (request_tree, tvb, offset-4, 4,
3466 "Request id: %u", request_id);
3469 response_flags = tvb_get_guint8( tvb, offset );
3473 proto_tree_add_text (request_tree, tvb, offset-1, 1,
3474 "Response flags: %s (%u)",
3475 match_strval(response_flags, sync_scope),
3479 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3482 proto_tree_add_text (request_tree, tvb, offset-3, 3,
3483 "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3487 dissect_target_address(tvb, pinfo, &offset, request_tree, header, stream_is_big_endian);
3489 /* length of operation string */
3490 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3493 proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3494 /**/ "Operation length: %u", len);
3499 if (check_col(pinfo->cinfo, COL_INFO))
3501 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3505 proto_tree_add_text (request_tree, tvb, offset - len, len,
3506 /**/ "Operation: %s", operation);
3513 * Register a cleanup function in case on of our tvbuff accesses
3514 * throws an exception. We need to clean up operation.
3516 CLEANUP_PUSH(g_free, operation);
3519 * Decode IOP::ServiceContextList
3522 decode_ServiceContextList(tvb, pinfo, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3525 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3526 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3527 * GIOP octet stream start.
3530 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3533 * Save FN,reqid,and operation for later. Add sub_handle later.
3534 * But only if user is NOT clicking.
3537 if (! pinfo->fd->flags.visited)
3538 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3539 request_id,operation,NULL);
3543 * Call sub dissector.
3544 * First try an find a explicit sub_dissector, then if that
3545 * fails, try the heuristic method.
3550 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3553 /* Only call heuristic if no explicit dissector was found */
3556 try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3561 * We're done with operation, so we can call the cleanup handler to free
3562 * it, and then pop the cleanup handler.
3564 CLEANUP_CALL_AND_POP;
3568 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3569 proto_tree * tree, MessageHeader * header,
3570 gboolean stream_is_big_endian)
3576 gchar *p_object_key;
3577 proto_tree *locate_request_tree = NULL;
3582 tf = proto_tree_add_text (tree, tvb, offset, -1,
3583 "General Inter-ORB Locate Request");
3584 if (locate_request_tree == NULL)
3586 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3591 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3592 if (check_col(pinfo->cinfo, COL_INFO))
3594 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3596 if (locate_request_tree)
3598 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3599 "Request id: %u", request_id);
3602 if(header->GIOP_version.minor < 2)
3604 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3605 if (locate_request_tree)
3607 proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3608 "Object Key length: %u", len);
3612 get_CDR_octet_seq(tvb, &object_key, &offset, len);
3614 p_object_key = make_printable_string(object_key, len);
3616 if(locate_request_tree)
3619 proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
3620 "Object Key: %s", p_object_key);
3623 g_free(p_object_key);
3627 else /* GIOP 1.2 and higher */
3629 dissect_target_address(tvb, pinfo, &offset, locate_request_tree, header,
3630 stream_is_big_endian);
3636 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3637 proto_tree * tree, MessageHeader * header,
3638 gboolean stream_is_big_endian)
3642 guint32 locate_status;
3645 proto_tree *locate_reply_tree = NULL;
3650 tf = proto_tree_add_text (tree, tvb, offset, -1,
3651 "General Inter-ORB Locate Reply");
3652 if (locate_reply_tree == NULL)
3654 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3659 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3660 if (check_col(pinfo->cinfo, COL_INFO))
3662 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3664 if (locate_reply_tree)
3666 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3667 "Request id: %u", request_id);
3670 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3671 if (locate_reply_tree)
3673 proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3674 "Locate status: %s",
3675 match_strval(locate_status, giop_locate_status_types)
3679 /* Decode the LocateReply body.
3681 * For GIOP 1.0 and 1.1 body immediately follows header.
3682 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3686 if (header->GIOP_version.minor > 1) {
3687 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3691 switch(locate_status) {
3692 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3693 case OBJECT_FORWARD_PERM:
3694 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3696 case LOC_SYSTEM_EXCEPTION:
3697 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3699 case LOC_NEEDS_ADDRESSING_MODE:
3700 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3701 if(locate_reply_tree) {
3702 proto_tree_add_text (tree, tvb, offset -2, 2,
3703 "AddressingDisposition: %u", addr_disp);
3706 default: /* others have no reply body */
3713 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3714 MessageHeader * header, gboolean stream_is_big_endian)
3718 proto_tree *fragment_tree = NULL;
3723 tf = proto_tree_add_text (tree, tvb, offset, -1,
3724 "General Inter-ORB Fragment");
3725 if (fragment_tree == NULL)
3727 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3732 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3733 if (check_col(pinfo->cinfo, COL_INFO))
3735 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3739 proto_tree_add_text (fragment_tree, tvb, offset-4, 4,
3740 "Request id: %u", request_id);
3746 /* Main entry point */
3748 gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3750 MessageHeader header;
3751 tvbuff_t *giop_header_tvb;
3752 tvbuff_t *payload_tvb;
3754 proto_tree *clnp_tree = NULL;
3757 u_int minor_version;
3758 gboolean stream_is_big_endian;
3764 giop_dump_collection(cd_module_hash);
3765 giop_dump_collection(cd_objkey_hash);
3766 giop_dump_collection(cd_heuristic_users);
3767 giop_dump_collection(cd_complete_reply_hash);
3768 giop_dump_collection(cd_complete_request_list);
3771 header.exception_id = NULL;
3773 /* check magic number and version */
3776 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
3778 if (tvb_length_remaining(tvb, 0) < GIOP_HEADER_SIZE)
3780 /* Not enough data captured to hold the GIOP header; don't try
3781 to interpret it as GIOP. */
3785 giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3786 payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3789 * because I have added extra elements in MessageHeader struct
3790 * for sub dissectors. -- FS
3793 tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3795 if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
3797 /* Not a GIOP message. */
3802 if (check_col (pinfo->cinfo, COL_PROTOCOL))
3804 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3807 if (header.GIOP_version.major != GIOP_MAJOR ||
3808 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3810 /* Bad version number; should we note that and dissect the rest
3811 as data, or should we return FALSE on the theory that it
3812 might have been some other packet that happened to begin with
3813 "GIOP"? We shouldn't do *both*, so we return TRUE, for now.
3814 If we should return FALSE, we should do so *without* setting
3815 the "Info" column, *without* setting the "Protocol" column,
3816 and *without* adding anything to the protocol tree. */
3818 if (check_col (pinfo->cinfo, COL_INFO))
3820 col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3821 header.GIOP_version.major, header.GIOP_version.minor);
3825 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3826 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3827 proto_tree_add_text (clnp_tree, giop_header_tvb, 0, -1,
3828 "Version %u.%u not supported",
3829 header.GIOP_version.major,
3830 header.GIOP_version.minor);
3832 call_dissector(data_handle,payload_tvb, pinfo, tree);
3836 if (check_col (pinfo->cinfo, COL_INFO))
3838 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3839 header.GIOP_version.major, header.GIOP_version.minor,
3840 val_to_str(header.message_type, giop_message_types,
3841 "Unknown message type (0x%02x)"));
3844 stream_is_big_endian = is_big_endian (&header);
3846 if (stream_is_big_endian)
3847 message_size = pntohl (&header.message_size);
3849 message_size = pletohl (&header.message_size);
3853 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, 12, FALSE);
3854 clnp_tree = proto_item_add_subtree (ti, ett_giop);
3855 proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3856 "Magic number: %s", GIOP_MAGIC);
3857 proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3859 header.GIOP_version.major,
3860 header.GIOP_version.minor);
3861 switch (minor_version)
3865 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3866 "Flags: 0x%02x (%s %s)",
3868 (stream_is_big_endian) ? "big-endian" : "little-endian",
3869 (header.flags & 0x02) ? " fragment" : "");
3872 proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3873 "Byte ordering: %s-endian",
3874 (stream_is_big_endian) ? "big" : "little");
3878 } /* minor_version */
3880 proto_tree_add_uint_format (clnp_tree,
3881 hf_giop_message_type,
3882 giop_header_tvb, 7, 1,
3883 header.message_type,
3884 "Message type: %s", match_strval(header.message_type, giop_message_types));
3886 proto_tree_add_uint (clnp_tree,
3887 hf_giop_message_size,
3888 giop_header_tvb, 8, 4, message_size);
3893 if (check_col (pinfo->cinfo, COL_INFO))
3895 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3896 header.GIOP_version.major, header.GIOP_version.minor,
3897 match_strval(header.message_type, giop_message_types));
3901 switch (header.message_type)
3905 if(header.GIOP_version.minor < 2)
3907 dissect_giop_request_1_1 (payload_tvb, pinfo, tree, clnp_tree,
3908 &header, stream_is_big_endian);
3912 dissect_giop_request_1_2 (payload_tvb, pinfo, tree, clnp_tree,
3913 &header, stream_is_big_endian);
3920 if(header.GIOP_version.minor < 2)
3922 dissect_giop_reply (payload_tvb, pinfo, tree, clnp_tree, &header,
3923 stream_is_big_endian);
3927 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree, clnp_tree,
3928 &header, stream_is_big_endian);
3932 dissect_giop_cancel_request(payload_tvb, pinfo, tree, clnp_tree,
3933 &header, stream_is_big_endian);
3936 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
3937 stream_is_big_endian);
3940 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
3941 stream_is_big_endian);
3944 dissect_giop_fragment(payload_tvb, pinfo, tree, &header,
3945 stream_is_big_endian);
3950 } /* switch message_type */
3954 * XXX - we should catch exceptions here, so that we can free
3955 * this if an exception is thrown.
3956 * We'd then have to forward the exception.
3958 if (header.exception_id != NULL)
3959 g_free(header.exception_id);
3965 proto_register_giop (void)
3967 static hf_register_info hf[] = {
3968 { &hf_giop_message_type,
3969 { "Message type", "giop.type",
3970 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
3973 { &hf_giop_message_size,
3974 { "Message size", "giop.len",
3975 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3979 { "Repository ID", "giop.repoid",
3980 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
3983 { &hf_giop_string_length,
3984 { "String Length", "giop.strlen",
3985 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3988 { &hf_giop_sequence_length,
3989 { "Sequence Length", "giop.seqlen",
3990 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3993 { &hf_giop_profile_id,
3994 { "Profile ID", "giop.profid",
3995 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
4000 { "IOR::type_id", "giop.typeid",
4001 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4004 { &hf_giop_iiop_v_maj,
4005 { "IIOP Major Version", "giop.iiop_vmaj",
4006 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4009 { &hf_giop_iiop_v_min,
4010 { "IIOP Minor Version", "giop.iiop_vmin",
4011 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4014 { &hf_giop_endianess,
4015 { "Endianess", "giop.endianess",
4016 FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4019 { &hf_giop_IIOP_tag,
4020 { "IIOP Component TAG", "giop.iioptag",
4021 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4025 { "IOR Profile TAG", "giop.iortag",
4026 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4030 { "TypeCode enum", "giop.TCKind",
4031 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4034 { &hf_giop_typecode_count,
4035 { "TypeCode count", "giop.tccount",
4036 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4039 { &hf_giop_typecode_default_used,
4040 { "default_used", "giop.tcdefault_used",
4041 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4044 { &hf_giop_typecode_digits,
4045 { "Digits", "giop.tcdigits",
4046 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4050 { &hf_giop_typecode_length,
4051 { "Length", "giop.tclength",
4052 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4055 { &hf_giop_typecode_max_length,
4056 { "Maximum length", "giop.tcmaxlen",
4057 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4060 { &hf_giop_typecode_member_name,
4061 { "TypeCode member name", "giop.tcmemname",
4062 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4065 { &hf_giop_typecode_name,
4066 { "TypeCode name", "giop.tcname",
4067 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4070 { &hf_giop_typecode_scale,
4071 { "Scale", "giop.tcscale",
4072 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4075 { &hf_giop_typecode_ValueModifier,
4076 { "ValueModifier", "giop.tcValueModifier",
4077 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4080 { &hf_giop_typecode_Visibility,
4081 { "Visibility", "giop.tcVisibility",
4082 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4087 { &hf_giop_type_boolean,
4088 { "TypeCode boolean data", "giop.tcboolean",
4089 FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
4092 { &hf_giop_type_char,
4093 { "TypeCode char data", "giop.tcchar",
4094 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4097 { &hf_giop_type_double,
4098 { "TypeCode double data", "giop.tcdouble",
4099 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4102 { &hf_giop_type_enum,
4103 { "TypeCode enum data", "giop.tcenumdata",
4104 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4108 * float as double ?? -- FIX
4111 { &hf_giop_type_float,
4112 { "TypeCode float data", "giop.tcfloat",
4113 FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
4116 { &hf_giop_type_long,
4117 { "TypeCode long data", "giop.tclongdata",
4118 FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4121 { &hf_giop_type_octet,
4122 { "TypeCode octet data", "giop.tcoctet",
4123 FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4126 { &hf_giop_type_short,
4127 { "TypeCode short data", "giop.tcshortdata",
4128 FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4131 { &hf_giop_type_string,
4132 { "TypeCode string data", "giop.tcstring",
4133 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4136 { &hf_giop_type_ulong,
4137 { "TypeCode ulong data", "giop.tculongdata",
4138 FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4141 { &hf_giop_type_ushort,
4142 { "TypeCode ushort data", "giop.tcushortdata",
4143 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4147 * IIOP Module - Chapter 15.10.2
4150 { &hf_giop_iiop_host,
4151 { "IIOP::Profile_host", "giop.iiop.host",
4152 FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4156 { &hf_giop_iiop_port,
4157 { "IIOP::Profile_port", "giop.iiop.port",
4158 FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4163 * IIOP ServiceContext
4166 { &hf_giop_iop_vscid,
4167 { "VSCID", "giop.iiop.vscid",
4168 FT_UINT32, BASE_HEX, NULL, 0xfffff000, "", HFILL }
4172 { &hf_giop_iop_scid,
4173 { "SCID", "giop.iiop.scid",
4174 FT_UINT32, BASE_HEX, NULL, 0x00000fff, "", HFILL }
4181 static gint *ett[] = {
4185 &ett_giop_cancel_request,
4186 &ett_giop_locate_request,
4187 &ett_giop_locate_reply,
4193 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4195 proto_register_field_array (proto_giop, hf, array_length (hf));
4196 proto_register_subtree_array (ett, array_length (ett));
4199 /* register init routine */
4201 register_init_routine( &giop_init); /* any init stuff */
4204 * Init the giop user module hash tables here, as giop users
4205 * will populate it via register_giop_user_module BEFORE my
4206 * own giop_init() is called.
4209 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4211 giop_module_keys = g_mem_chunk_new("giop_module_keys",
4212 sizeof(struct giop_module_key),
4213 giop_module_init_count * sizeof(struct giop_module_key),
4216 giop_module_vals = g_mem_chunk_new("giop_module_vals",
4217 sizeof(struct giop_module_val),
4218 giop_module_init_count * sizeof(struct giop_module_val),
4225 void proto_reg_handoff_giop (void) {
4226 data_handle = find_dissector("data");
4227 heur_dissector_add("tcp", dissect_giop, proto_giop);
4228 /* Support DIOP (GIOP/UDP) */
4229 heur_dissector_add("udp", dissect_giop, proto_giop);
4238 * Ref Corba v2.4.2 Chapter 13
4246 typedef unsigned long ProfileId;
4248 const ProfileId TAG_INTERNET_IOP = 0;
4249 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4251 struct TaggedProfile {
4253 sequence <octet> profile_data;
4258 sequence <TaggedProfile> profiles;
4261 typedef unsigned long ComponentId;
4263 struct TaggedComponent {
4265 sequence <octet> component_data;
4268 typedef sequence <TaggedComponent> MultipleComponentProfile;
4274 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4275 guint32 boundary, gboolean stream_is_big_endian) {
4278 guint32 seqlen_p; /* sequence length of profiles */
4281 proto_tree *tree = NULL; /* IOR tree */
4284 gchar *repobuf; /* for repository ID */
4288 /* create a subtree */
4291 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
4292 tree = proto_item_add_subtree (tf, ett_giop_ior);
4296 /* Get type_id == Repository ID */
4298 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4301 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4302 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4304 proto_tree_add_string(tree,hf_giop_type_id,tvb,
4305 *offset-u_octet4,u_octet4,repobuf);
4310 * Register a cleanup function in case on of our tvbuff accesses
4311 * throws an exception. We need to clean up repobuf.
4312 * We can't free it yet, as we must wait until we have the object
4313 * key, as we have to add both to the hash table.
4315 CLEANUP_PUSH(g_free, repobuf);
4317 /* Now get a sequence of profiles */
4318 /* Get sequence length (number of elements) */
4320 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4322 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4323 *offset-sizeof(seqlen_p),4,seqlen_p);
4327 /* fetch all TaggedProfiles in this sequence */
4329 for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4330 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4334 * We're done with repobuf, so we can call the cleanup handler to free
4335 * it, and then pop the cleanup handler.
4337 CLEANUP_CALL_AND_POP;
4341 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4342 guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4344 guint32 seqlen_pd; /* sequence length of profile data */
4346 guint32 pidtag; /* profile ID TAG */
4348 gchar *profile_data; /* profile_data pointer */
4349 gchar *p_profile_data; /* printable profile_data pointer */
4351 guint32 new_boundary; /* for encapsulations encountered */
4352 gboolean new_big_endianess; /* for encapsulations encountered */
4354 /* Get ProfileId tag */
4356 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4359 proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4360 *offset-sizeof(pidtag),4,pidtag);
4363 /* get sequence length, new endianness and boundary for encapsulation */
4365 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
4366 stream_is_big_endian, boundary,
4367 &new_big_endianess, &new_boundary);
4369 /* return if zero length sequence */
4376 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
4377 * decode it, otherwise just dump the octet sequence
4379 * also, store IOR in our objectkey hash
4381 * TODO - handle other TAGS
4385 case IOP_TAG_INTERNET_IOP:
4387 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4392 /* fetch all octets in this sequence , but skip endianess */
4394 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4396 /* Make a printable string */
4398 p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4401 proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4402 "Profile Data: %s", p_profile_data);
4405 g_free(p_profile_data);
4407 g_free(profile_data);
4418 * Decode IIOP IOR Profile
4419 * Ref Chap 15.7.2 in Corba Spec
4423 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4424 guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4425 gboolean store_flag) {
4427 guint32 i; /* loop index */
4429 guint8 v_major,v_minor; /* IIOP sersion */
4431 guint32 u_octet4; /* u long */
4432 guint16 u_octet2; /* u short */
4433 guint32 seqlen; /* generic sequence length */
4434 guint32 seqlen1; /* generic sequence length */
4435 gchar *objkey; /* object key pointer */
4436 gchar *p_chars; /* printable characters pointer */
4439 /* Get major/minor version */
4441 v_major = get_CDR_octet(tvb,offset);
4442 v_minor = get_CDR_octet(tvb,offset);
4446 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4447 *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
4448 proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4449 *offset-sizeof(v_minor),1,v_minor );
4455 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4458 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4459 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4461 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4462 *offset-u_octet4,u_octet4,buf);
4466 g_free(buf); /* dont forget */
4470 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4473 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4474 *offset-sizeof(u_octet2),2,u_octet2);
4478 /* Object Key - sequence<octet> object_key */
4480 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4483 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4484 *offset-sizeof(seqlen),4,seqlen);
4488 /* fetch all octets in this sequence */
4489 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4492 * Now we may have the Repository ID from earlier, as well
4493 * as the object key sequence and lengh. So lets store them in
4494 * our objectkey hash and free buffers.
4496 * But only insert if user is not clicking and repo id not NULL.
4502 if(!pinfo->fd->flags.visited)
4503 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
4508 * No pinfo, but store anyway if flag set. eg: IOR read from file
4512 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
4516 /* Make a printable string */
4518 p_chars = make_printable_string( objkey, seqlen );
4521 proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
4522 "Object Key: %s", p_chars);
4530 * Now see if if its v1.1 or 1.2, as they can contain
4531 * extra sequence of IOP::TaggedComponents
4544 /* sequence of IOP::TaggedComponents */
4545 /* Ref Chap 13 in Corba Spec */
4547 /* get sequence length */
4548 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4551 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4552 *offset-sizeof(seqlen),4,seqlen);
4555 for (i=0; i< seqlen; i++) {
4557 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4559 proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4560 *offset-sizeof(u_octet4),4,u_octet4);
4563 /* get component_data */
4564 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4566 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4567 *offset-sizeof(seqlen1),4,seqlen1);
4571 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4574 /* Make a printable string of data */
4576 p_chars = make_printable_string(buf, seqlen1);
4578 proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4579 "component_data: %s", p_chars);
4593 g_warning("giop:Invalid v_minor value = %u ", v_minor);
4601 * Service Contexts Begin
4609 void dissect_SID_BI_DIR_IIOP(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4610 MessageHeader *header, gchar *operation, guint32 boundary) {
4620 * Service Contexts End
4632 * typedef unsigned long ServiceID;
4634 * struct ServiceContext {
4635 * ServiceID context_id;
4636 * sequence <octet> context_data;
4638 * typedef sequence <ServiceContext> ServiceContextList;
4641 * Note: Spec says context_data is an encapsulation.
4648 void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4649 gboolean stream_is_be, guint32 boundary) {
4651 guint32 seqlen; /* sequence length */
4652 guint32 seqlen_cd; /* sequence length, context_data */
4654 proto_tree *tree = NULL; /* ServiceContext tree */
4658 gchar *context_data;
4659 gchar *p_context_data;
4662 guint32 vscid; /* Vendor Service context id */
4665 /* create a subtree */
4668 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "ServiceContextList");
4669 tree = proto_item_add_subtree (tf, ett_giop_scl);
4672 /* Get sequence length (number of elements) */
4674 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4676 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4677 *offset-sizeof(seqlen),4,seqlen);
4680 /* return if zero length sequence */
4685 /* Loop for all ServiceContext's */
4687 for (i=0; i<seqlen; i++) {
4689 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4691 proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4692 *offset-sizeof(context_id),4,context_id);
4694 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4695 *offset-sizeof(context_id),4,context_id);
4699 vscid = context_id && 0xfffff000; /* vendor info, top 20 bits */
4700 scid = context_id && 0x00000fff; /* standard service info, lower 12 bits */
4703 #if CONTEXT_DATA_IS_ENCAPSULATED
4705 /* get sequence length, new endianness and boundary for encapsulation */
4707 seqlen_cd = get_CDR_encap_info(tvb, tree, offset,
4708 stream_is_be, boundary,
4709 &new_big_endianess, &new_boundary);
4713 /* get sequence length, and NO encapsulation */
4715 seqlen_cd = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4719 /* return if zero length sequence */
4725 * Now decode sequence according to vendor ServiceId, but I dont
4726 * have that yet, so just dump it as data.
4729 /* fetch all octets in this sequence */
4731 get_CDR_octet_seq(tvb, &context_data, offset, seqlen_cd);
4733 /* Make a printable string */
4735 p_context_data = make_printable_string( context_data, seqlen_cd );
4738 proto_tree_add_text (tree, tvb, *offset - seqlen_cd , seqlen_cd,
4739 "context_data: %s", p_context_data);
4742 g_free(context_data);
4743 g_free(p_context_data);
4748 return; /* for now, fix later */
4753 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
4756 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
4757 gboolean stream_is_big_endian,
4760 guint32 length; /* string length */
4761 guint32 minor_code_value;
4762 guint32 completion_status;
4764 gchar *buf; /* pointer to string buffer */
4766 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
4769 proto_tree_add_text(tree, tvb, *offset-4, 4,
4770 "Exception length: %u", length);
4772 proto_tree_add_text(tree, tvb, *offset - length, length,
4773 "Exception id: %s", buf );
4778 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4779 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4782 proto_tree_add_text(tree, tvb, *offset-8, 4,
4783 "Minor code value: %u", minor_code_value);
4784 proto_tree_add_text(tree, tvb, *offset-4, 4,
4785 "Completion Status: %u", completion_status);
4791 * Helper functions for dissecting TypeCodes
4793 * These functions decode the complex parameter lists
4794 * of TypeCodes as defined in the CORBA spec chapter 15.
4797 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4798 gboolean stream_is_big_endian, guint32 boundary,
4799 MessageHeader * header) {
4801 guint32 new_boundary; /* new boundary for encapsulation */
4802 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4804 guint32 seqlen; /* sequence length */
4806 /* get sequence length, new endianness and boundary for encapsulation */
4807 seqlen = get_CDR_encap_info(tvb, tree, offset,
4808 stream_is_big_endian, boundary,
4809 &new_stream_is_big_endian, &new_boundary);
4811 /* get repository ID */
4812 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4816 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4817 hf_giop_typecode_name);
4822 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4823 gboolean stream_is_big_endian, guint32 boundary,
4824 MessageHeader * header ) {
4826 guint32 new_boundary; /* new boundary for encapsulation */
4827 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4829 guint32 count; /* parameter count (of tuples) */
4830 guint32 seqlen; /* sequence length */
4831 guint32 i; /* loop index */
4833 /* get sequence lengt,h new endianness and boundary for encapsulation */
4834 seqlen = get_CDR_encap_info(tvb, tree, offset,
4835 stream_is_big_endian, boundary,
4836 &new_stream_is_big_endian, &new_boundary);
4838 /* get repository ID */
4839 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4843 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4844 hf_giop_typecode_name);
4846 /* get count of tuples */
4847 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4849 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4850 *offset-sizeof(count),4,count);
4853 /* get all tuples */
4854 for (i=0; i< count; i++) {
4855 /* get member name */
4856 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4857 hf_giop_typecode_member_name);
4859 /* get member type */
4860 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4866 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4867 gboolean stream_is_big_endian, guint32 boundary,
4868 MessageHeader * header) {
4870 guint32 new_boundary; /* new boundary for encapsulation */
4871 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4873 guint32 TCKind; /* TypeCode */
4874 gint32 s_octet4; /* signed int32 */
4876 guint32 count; /* parameter count (of tuples) */
4877 guint32 seqlen; /* sequence length */
4878 guint32 i; /* loop index */
4880 /* get sequence legnth, new endianness and boundary for encapsulation */
4881 seqlen = get_CDR_encap_info(tvb, tree, offset,
4882 stream_is_big_endian, boundary,
4883 &new_stream_is_big_endian, &new_boundary);
4885 /* get repository ID */
4886 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4890 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4891 hf_giop_typecode_name);
4893 /* get discriminant type */
4894 TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4896 /* get default used */
4897 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
4899 proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
4900 *offset-sizeof(s_octet4),4,s_octet4);
4902 /* get count of tuples */
4903 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4905 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4906 *offset-sizeof(count),4,count);
4909 /* get all tuples */
4910 for (i=0; i< count; i++) {
4911 /* get label value, based on TCKind above */
4912 dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
4914 /* get member name */
4915 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4916 hf_giop_typecode_member_name);
4918 /* get member type */
4919 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4925 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4926 gboolean stream_is_big_endian, guint32 boundary,
4927 MessageHeader * header) {
4929 guint32 new_boundary; /* new boundary for encapsulation */
4930 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4932 guint32 count; /* parameter count (of tuples) */
4933 guint32 seqlen; /* sequence length */
4934 guint32 i; /* loop index */
4936 /* get sequence length, new endianness and boundary for encapsulation */
4937 seqlen = get_CDR_encap_info(tvb, tree, offset,
4938 stream_is_big_endian, boundary,
4939 &new_stream_is_big_endian, &new_boundary);
4941 /* get repository ID */
4942 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4946 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4947 hf_giop_typecode_name);
4949 /* get count of tuples */
4950 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4952 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4953 *offset-sizeof(count),4,count);
4956 /* get all tuples */
4957 for (i=0; i< count; i++) {
4958 /* get member name */
4959 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4960 hf_giop_typecode_member_name);
4966 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4967 gboolean stream_is_big_endian, guint32 boundary,
4968 MessageHeader * header) {
4970 guint32 new_boundary; /* new boundary for encapsulation */
4971 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4973 guint32 u_octet4; /* unsigned int32 */
4975 guint32 seqlen; /* sequence length */
4977 /* get sequence length, new endianness and boundary for encapsulation */
4978 seqlen = get_CDR_encap_info(tvb, tree, offset,
4979 stream_is_big_endian, boundary,
4980 &new_stream_is_big_endian, &new_boundary);
4982 /* get element type */
4983 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4985 /* get max length */
4986 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4988 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
4989 *offset-sizeof(u_octet4),4,u_octet4);
4994 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
4995 gboolean stream_is_big_endian, guint32 boundary,
4996 MessageHeader * header) {
4998 guint32 new_boundary; /* new boundary for encapsulation */
4999 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5001 guint32 u_octet4; /* unsigned int32 */
5003 guint32 seqlen; /* sequence length */
5005 /* get sequence length, new endianness and boundary for encapsulation */
5006 seqlen = get_CDR_encap_info(tvb, tree, offset,
5007 stream_is_big_endian, boundary,
5008 &new_stream_is_big_endian, &new_boundary);
5010 /* get element type */
5011 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5014 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5016 proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5017 *offset-sizeof(u_octet4),4,u_octet4);
5022 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5023 gboolean stream_is_big_endian, guint32 boundary,
5024 MessageHeader * header) {
5026 guint32 new_boundary; /* new boundary for encapsulation */
5027 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5029 guint32 seqlen; /* sequence length */
5031 /* get sequence legnth, new endianness and boundary for encapsulation */
5032 seqlen = get_CDR_encap_info(tvb, tree, offset,
5033 stream_is_big_endian, boundary,
5034 &new_stream_is_big_endian, &new_boundary);
5036 /* get repository ID */
5037 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5041 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5042 hf_giop_typecode_name);
5044 /* get ??? (noname) TypeCode */
5045 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5050 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5051 gboolean stream_is_big_endian, guint32 boundary,
5052 MessageHeader * header) {
5054 guint32 new_boundary; /* new boundary for encapsulation */
5055 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5057 guint32 count; /* parameter count (of tuples) */
5058 guint32 seqlen; /* sequence length */
5059 guint32 i; /* loop index */
5061 /* get sequence length, new endianness and boundary for encapsulation */
5062 seqlen = get_CDR_encap_info(tvb, tree, offset,
5063 stream_is_big_endian, boundary,
5064 &new_stream_is_big_endian, &new_boundary);
5066 /* get repository ID */
5067 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5071 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5072 hf_giop_typecode_name);
5074 /* get count of tuples */
5075 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5077 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5078 *offset-sizeof(count),4,count);
5081 /* get all tuples */
5082 for (i=0; i< count; i++) {
5083 /* get member name */
5084 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5085 hf_giop_typecode_member_name);
5087 /* get member type */
5088 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5094 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5095 gboolean stream_is_big_endian, guint32 boundary,
5096 MessageHeader * header) {
5098 guint32 new_boundary; /* new boundary for encapsulation */
5099 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5101 gint16 s_octet2; /* signed int16 */
5103 guint32 count; /* parameter count (of tuples) */
5104 guint32 seqlen; /* sequence length */
5105 guint32 i; /* loop index */
5107 /* get sequence length, new endianness and boundary for encapsulation */
5108 seqlen = get_CDR_encap_info(tvb, tree, offset,
5109 stream_is_big_endian, boundary,
5110 &new_stream_is_big_endian, &new_boundary);
5112 /* get repository ID */
5113 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5117 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5118 hf_giop_typecode_name);
5120 /* get ValueModifier */
5121 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5123 proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5124 *offset-sizeof(s_octet2),2,s_octet2);
5127 /* get conrete base */
5128 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5130 /* get count of tuples */
5131 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5133 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5134 *offset-sizeof(count),4,count);
5137 /* get all tuples */
5138 for (i=0; i< count; i++) {
5139 /* get member name */
5140 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5141 hf_giop_typecode_member_name);
5143 /* get member type */
5144 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5146 /* get Visibility */
5147 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5149 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5150 *offset-sizeof(s_octet2),2,s_octet2);
5157 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5158 gboolean stream_is_big_endian, guint32 boundary,
5159 MessageHeader * header) {
5161 guint32 new_boundary; /* new boundary for encapsulation */
5162 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5164 guint32 seqlen; /* sequence length */
5166 /* get sequence length, new endianness and boundary for encapsulation */
5167 seqlen = get_CDR_encap_info(tvb, tree, offset,
5168 stream_is_big_endian, boundary,
5169 &new_stream_is_big_endian, &new_boundary);
5171 /* get repository ID */
5172 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5176 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5177 hf_giop_typecode_name);
5179 /* get ??? (noname) TypeCode */
5180 get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5184 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5185 gboolean stream_is_big_endian, guint32 boundary,
5186 MessageHeader * header) {
5188 guint32 new_boundary; /* new boundary for encapsulation */
5189 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5191 guint32 seqlen; /* sequence length */
5193 /* get sequence length, new endianness and boundary for encapsulation */
5194 seqlen = get_CDR_encap_info(tvb, tree, offset,
5195 stream_is_big_endian, boundary,
5196 &new_stream_is_big_endian, &new_boundary);
5198 /* get repository ID */
5199 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5203 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5204 hf_giop_typecode_name);
5209 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5210 gboolean stream_is_big_endian, guint32 boundary,
5211 MessageHeader * header) {
5213 guint32 new_boundary; /* new boundary for encapsulation */
5214 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5216 guint32 seqlen; /* sequence length */
5218 /* get sequence length, new endianness and boundary for encapsulation */
5219 seqlen = get_CDR_encap_info(tvb, tree, offset,
5220 stream_is_big_endian, boundary,
5221 &new_stream_is_big_endian, &new_boundary);
5223 /* get repository ID */
5224 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5228 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5229 hf_giop_typecode_name);
5233 /* Typecode parameter lists are encoded as encapsulations and
5234 * this function gets the encapsulation information; see
5235 * CORBA spec chapter 15
5238 * Renamed to get_CDR_encap_info() for any encapsulation
5239 * we come across, useful helper function
5241 * Also, should return immediately if seqlen == 0.
5242 * ie: Forget about trying to grab endianess for
5243 * zero length sequence.
5245 * Caller must always check seqlen == 0, and not assume its value
5248 * Note: there seemed to be considerable confusion in corba
5249 * circles as to the correct interpretation of encapsulations,
5250 * and zero length sequences etc, but this is our best bet at the
5257 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5258 gboolean old_stream_is_big_endian, guint32 old_boundary,
5259 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5261 guint32 seqlen; /* sequence length */
5262 guint8 giop_endianess;
5264 /* Get sequence length of parameter list */
5265 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5267 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5268 *offset-sizeof(seqlen),4,seqlen);
5274 * seqlen == 0, implies no endianess and no data
5275 * so just return. Populate new_boundary_ptr and
5276 * new_stream_is_big_endian_ptr with current (old)
5277 * values, just to keep everyone happy. -- FS
5283 *new_boundary_ptr = old_boundary;
5284 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5290 /* Start of encapsulation of parameter list */
5291 *new_boundary_ptr = *offset; /* remember */
5292 giop_endianess = get_CDR_octet(tvb,offset);
5294 *new_stream_is_big_endian_ptr = ! giop_endianess;
5297 * Glib: typedef gint gboolean;
5298 * ie: It is not a guint8, so cannot use sizeof to correctly
5304 proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5305 *offset-1,1,giop_endianess);
5315 * gets a TypeCode complex string parameter and
5316 * displays it in the relevant tree.
5319 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5320 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5322 guint32 u_octet4; /* unsigned int32 */
5323 gchar *buf; /* ptr to string buffer */
5326 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5329 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5330 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5332 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5336 g_free(buf); /* dont forget */
5341 * For a given data type, given by a TypeCode gets the associated data
5342 * and displays it in the relevant tree.
5345 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
5346 gboolean stream_is_big_endian, guint32 boundary,
5347 MessageHeader * header, guint32 data_type ) {
5349 gboolean my_boolean; /* boolean */
5351 gint8 s_octet1; /* signed int8 */
5352 guint8 u_octet1; /* unsigned int8 */
5354 gint16 s_octet2; /* signed int16 */
5355 guint16 u_octet2; /* unsigned int16 */
5357 gint32 s_octet4; /* signed int32 */
5358 guint32 u_octet4; /* unsigned int32 */
5360 gdouble my_double; /* double */
5361 gfloat my_float; /* float */
5363 gchar *buf = NULL; /* ptr to string buffer */
5365 /* Grab the data according to data type */
5367 switch (data_type) {
5369 /* nothing to decode */
5372 /* nothing to decode */
5375 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5377 proto_tree_add_int(tree,hf_giop_type_short,tvb,
5378 *offset-sizeof(s_octet2),2,s_octet2);
5382 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5384 proto_tree_add_int(tree,hf_giop_type_long,tvb,
5385 *offset-sizeof(s_octet4),4,s_octet4);
5389 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5391 proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5392 *offset-sizeof(u_octet2),2,u_octet2);
5396 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5398 proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5399 *offset-sizeof(u_octet4),4,u_octet4);
5403 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5405 proto_tree_add_double(tree,hf_giop_type_float,tvb,
5406 *offset-sizeof(my_float),4,my_float);
5410 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5412 proto_tree_add_double(tree,hf_giop_type_double,tvb,
5413 *offset-sizeof(my_double),8,my_double);
5417 my_boolean = get_CDR_boolean(tvb,offset);
5419 proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5420 *offset-1,1,my_boolean);
5424 u_octet1 = get_CDR_char(tvb,offset);
5426 proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5427 *offset-sizeof(u_octet1),1,u_octet1);
5431 u_octet1 = get_CDR_octet(tvb,offset);
5433 proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5434 *offset-sizeof(u_octet1),1,u_octet1);
5438 get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5441 get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5452 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5454 proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5455 *offset-sizeof(u_octet4),4,u_octet4);
5459 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5461 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5462 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5464 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5465 *offset-u_octet4,u_octet4,buf);
5469 g_free(buf); /* dont forget */
5486 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5489 * XXX - can any of these throw an exception?
5490 * If so, we need to catch the exception and free "buf".
5492 if (s_octet1 < 0) { /* no size to add to tree */
5493 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5494 *offset+s_octet1,(-s_octet1),buf);
5496 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5497 *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5498 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5499 *offset-s_octet1,s_octet1,buf);
5503 g_free(buf); /* dont forget */
5506 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5509 * XXX - can any of these throw an exception?
5510 * If so, we need to catch the exception and free "buf".
5512 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5513 *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5514 proto_tree_add_string(tree,hf_giop_type_string,tvb,
5515 *offset-u_octet4,u_octet4,buf);
5518 g_free(buf); /* dont forget */
5528 case tk_abstract_interface:
5531 g_warning("giop: Unknown typecode data type %u \n", data_type);