"uint" is defined on all platforms; use "guint" instead.
[obnox/wireshark/wip.git] / packet-giop.c
1 /* packet-giop.c
2  * Routines for CORBA GIOP/IIOP packet disassembly
3  *
4  * Initial Code by,
5  * Laurent Deniel <deniel@worldnet.fr>
6  * Craig Rodrigues <rodrigc@mediaone.net>
7  * 
8  * GIOP API extensions by,
9  * Frank Singleton <frank.singleton@ericsson.com>
10  * Trevor Shepherd <eustrsd@am1.ericsson.se>
11  *
12  * $Id: packet-giop.c,v 1.61 2002/05/13 01:24:45 guy Exp $
13  *
14  * Ethereal - Network traffic analyzer
15  * By Gerald Combs <gerald@ethereal.com>
16  * Copyright 1998 Gerald Combs
17  * 
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.
22  * 
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.
27  * 
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.
31  */
32
33
34 /*
35  * TODO: -- FS
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.]
48  *
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]
57  *
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
66  *     to a sub_dissector.
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() ]
80  *     
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]
84  *
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]
97  *
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.
103  *
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).
110  *
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
113  *
114  */
115
116
117
118 /*
119  * Intended Decode strategy:
120  * =========================
121  *
122  * Initial Pass
123  * ------------
124  * REQUEST: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
125  *          and populate complete_request_packet_hash
126  *
127  * REPLY:   FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
128  *
129  * User Clicks
130  * -----------
131  *
132  * REQUEST: FN -> giop_sub_handle_t directly (via complete_request_packet_hash)
133  *
134  * REPLY:   FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
135  *                                                                     (via complete_request_packet_hash
136  *
137  *
138  * Limitations. 
139  * ============
140  *
141  * 1. Request_ID's are unique only per connection.
142  *
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.
149  *
150  *    TODO -- Read stringified IORs from an input file.[done]
151  *
152  * 3. User clicks (REQUEST) is currently handle the same as
153  *    the initial pass handling.
154  *
155  *    ie: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
156  */
157
158
159 /*
160  * Important Data Structures:
161  *
162  * giop_module_hash 
163  * ----------------
164  *
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.
171  *
172  * 
173  * giop_sub_list
174  * -------------
175  *
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.
180  *
181  * 
182  * giop_objkey_hash
183  * ----------------
184  *
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.
190  *
191  * So, I listen in on REQUEST(resolve) messages between client and
192  * Nameserver, and store the respones (REPLY/Objkey,Repo_ID) here.
193  *
194  * Also, stringified IOR's can be read from a file "IOR.txt" and used
195  * to populate  this hash also.
196  *
197  *
198  * Other Data structures 
199  * =======================
200  *
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.
206  *
207  *
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 ??)
212  * 
213  * Abbrevs:
214  * --------
215  *
216  * FN  - Frame Number
217  * MFN - Matching Frame Number
218  *
219  *
220  * complete_request_packet_list
221  * ----------------------------
222  *
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
225  *
226  * complete_reply_packet_hash
227  * --------------------------
228  *
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. 
234  *
235  * The algorithm I use to populate this hash during initial pass,
236  * is as follows. 
237  *
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.
243  *
244  *
245  * See TODO for improvements to above algorithm.
246  *
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.
249  *
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.
253  *
254  * So, how do I differentiate between the initial processing of incoming
255  * packets, and a user clickin on one ? Good question.
256  *
257  * I leverage the pinfo_fd->flags.visited  on a per frame
258  * basis. 
259  *
260  * To quote from the ever helpful development list
261  *
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).
268
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.
272
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".  "
277  *
278  */
279
280
281 #ifdef HAVE_CONFIG_H
282 # include "config.h"
283 #endif
284
285 #ifdef HAVE_SYS_TYPES_H
286 # include <sys/types.h>
287 #endif
288
289 #include <string.h>
290 #include <stdio.h>
291 #include <errno.h>
292 #include <ctype.h>
293 #include <glib.h>
294 #include <math.h>
295 #ifdef NEED_STRERROR_H
296 #include "strerror.h"
297 #endif
298
299 #include <epan/packet.h>
300 #include "packet-giop.h"
301
302 /*
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 
306  *
307  */
308
309 #define CONTEXT_DATA_IS_ENCAPSULATED  0
310
311
312 /*
313  * Set to 1 for DEBUG output - TODO make this a runtime option
314  */
315
316 #define DEBUG   0
317
318
319
320 /*
321  * ------------------------------------------------------------------------------------------+ 
322  *                                 Private Helper function Declarations
323  * ------------------------------------------------------------------------------------------+
324  */
325
326
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);
330
331 static void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *tree, int *offset,
332                                       gboolean stream_is_be, guint32 boundary);
333
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);
336
337 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
338                        guint32 boundary, gboolean stream_is_big_endian );
339
340 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
341                                              gboolean stream_is_big_endian,
342                                              guint32 boundary);
343
344 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
345                                      gboolean stream_is_big_endian, guint32 boundary);
346
347 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
348                                      gboolean stream_is_big_endian, guint32 boundary,
349                                      MessageHeader * header);
350
351 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
352                                     gboolean stream_is_big_endian, guint32 boundary,
353                                     MessageHeader * header );
354  
355 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
356                                    gboolean stream_is_big_endian, guint32 boundary);
357
358 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
359                                        gboolean stream_is_big_endian, guint32 boundary,
360                                        MessageHeader * header);
361
362 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
363                                     gboolean stream_is_big_endian, guint32 boundary,
364                                     MessageHeader * header);
365
366 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
367                                     gboolean stream_is_big_endian, guint32 boundary,
368                                     MessageHeader * header);
369
370 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
371                                      gboolean stream_is_big_endian, guint32 boundary,
372                                      MessageHeader * header);
373
374 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
375                                     gboolean stream_is_big_endian, guint32 boundary,
376                                     MessageHeader * header);
377
378 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
379                                         gboolean stream_is_big_endian, guint32 boundary,
380                                         MessageHeader * header);
381
382 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
383                                      gboolean stream_is_big_endian, guint32 boundary);
384
385 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
386                                                  gboolean stream_is_big_endian, guint32 boundary);
387
388
389 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
390                                           gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
391
392 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
393                                       gboolean stream_is_big_endian, guint32 boundary,
394                                       MessageHeader * header, guint32 data_type );
395
396
397
398
399 /*
400  * ------------------------------------------------------------------------------------------+ 
401  *                                 Data/Variables/Structs
402  * ------------------------------------------------------------------------------------------+
403  */
404
405
406 static int proto_giop = -1;
407 static int hf_giop_message_type = -1;
408 static int hf_giop_message_size = -1;
409 static int hf_giop_repoid = -1;
410 static int hf_giop_string_length = -1;
411 static int hf_giop_sequence_length = -1;
412 static int hf_giop_profile_id = -1;
413 static int hf_giop_type_id = -1;
414 static int hf_giop_iiop_v_maj = -1;
415 static int hf_giop_iiop_v_min = -1;
416 static int hf_giop_endianess = -1; /* esp encapsulations */
417 static int hf_giop_IOR_tag = -1; 
418 static int hf_giop_IIOP_tag = -1;
419
420 static int hf_giop_TCKind = -1;
421 static int hf_giop_typecode_count = -1;
422 static int hf_giop_typecode_default_used = -1;
423 static int hf_giop_typecode_digits = -1;
424 static int hf_giop_typecode_length = -1;
425 static int hf_giop_typecode_max_length = -1;
426 static int hf_giop_typecode_member_name = -1;
427 static int hf_giop_typecode_name = -1;
428 static int hf_giop_typecode_scale = -1;
429 static int hf_giop_typecode_ValueModifier = -1;
430 static int hf_giop_typecode_Visibility = -1;
431
432 static int hf_giop_type_boolean = -1;
433 static int hf_giop_type_char = -1;
434 static int hf_giop_type_double = -1;
435 static int hf_giop_type_enum = -1;
436 static int hf_giop_type_float = -1;
437 static int hf_giop_type_long = -1;
438 static int hf_giop_type_octet = -1;
439 static int hf_giop_type_short = -1;
440 static int hf_giop_type_string = -1;
441 static int hf_giop_type_ulong = -1;
442 static int hf_giop_type_ushort = -1;
443
444 static int hf_giop_iiop_host = -1; 
445 static int hf_giop_iiop_port = -1; 
446 static int hf_giop_iop_vscid = -1;
447 static int hf_giop_iop_scid = -1;
448
449 /*
450  * (sub)Tree declares
451  */
452
453 static gint ett_giop = -1;
454 static gint ett_giop_reply = -1;
455 static gint ett_giop_request = -1;
456 static gint ett_giop_cancel_request = -1;
457 static gint ett_giop_locate_request = -1;
458 static gint ett_giop_locate_reply = -1;
459 static gint ett_giop_fragment = -1;
460
461 static gint ett_giop_scl = -1;  /* ServiceContextList */
462 static gint ett_giop_ior = -1;  /* IOR  */
463
464 static dissector_handle_t data_handle;
465 /* GIOP endianess */
466
467 static const value_string giop_endianess_vals[] = {
468   { 0x0, "Big Endian" },
469   { 0x1, "Little Endian" },
470   { 0, NULL}
471 };
472
473 static const value_string sync_scope[] = {
474         { 0x0, "SYNC_NONE" },
475         { 0x1, "SYNC_WITH_TRANSPORT"},
476         { 0x2, "SYNC_WITH_SERVER"},
477         { 0x3, "SYNC_WITH_TARGET"},
478         { 0, NULL}
479 };
480
481 /* Profile ID's */
482
483 static const value_string profile_id_vals[] = {
484         { 0x0, "TAG_INTERNET_IOP" },
485         { 0x1, "TAG_MULTIPLE_COMPONENTS"},
486         { 0x2, "TAG_SCCP_IOP"},
487         { 0, NULL}
488 };
489
490 static const value_string giop_message_types[] = {
491         { 0x0, "Request" },
492         { 0x1, "Reply"},
493         { 0x2, "CancelRequest"},
494         { 0x3, "LocateRequest"},
495         { 0x4, "LocateReply"},
496         { 0x5, "CloseConnection"},
497         { 0x6, "MessageError"},
498         { 0x7, "Fragment"},
499         { 0, NULL}
500 };
501
502 static const value_string giop_locate_status_types[] = {
503         { 0x0, "Unknown Object" },
504         { 0x1, "Object Here"},
505         { 0x2, "Object Forward"},
506         { 0x3, "Object Forward Perm"},
507         { 0x4, "Loc System Exception"},
508         { 0x5, "Loc Needs Addressing Mode"},
509         { 0, NULL }     
510 };
511
512 static const value_string tckind_vals[] = {
513   { 0, "tk_null"},
514   { 1, "tk_void"},
515   { 2, "tk_short"},
516   { 3, "tk_long"},
517   { 4, "tk_ushort"},
518   { 5, "tk_ulong"},
519   { 6, "tk_float"},
520   { 7, "tk_double"},
521   { 8, "tk_boolean"},
522   { 9, "tk_char"},
523   { 10, "tk_octet"},
524   { 11, "tk_any"},
525   { 12, "tk_TypeCode"},
526   { 13, "tk_Principal"},
527   { 14, "tk_objref"},
528   { 15, "tk_struct"},
529   { 16, "tk_union"},
530   { 17, "tk_enum"},
531   { 18, "tk_string"},
532   { 19, "tk_sequence"},
533   { 20, "tk_array"},
534   { 21, "tk_alias"},
535   { 22, "tk_except"},
536   { 23, "tk_longlong"},
537   { 24, "tk_ulonglong"},
538   { 25, "tk_longdouble"},
539   { 26, "tk_wchar"},
540   { 27, "tk_wstring"},
541   { 28, "tk_fixed"},
542   { 29, "tk_value"},
543   { 30, "tk_value_box"},
544   { 31, "tk_native"},
545   { 32, "tk_abstract_interface"},
546   { 0, NULL }   
547 };
548
549
550
551 #define GIOP_MAGIC       "GIOP"
552
553 /*
554  * TAGS for IOR Profiles
555  *
556  * Chapter 13 Corba 2.4.2
557  *
558  */
559
560 #define IOP_TAG_INTERNET_IOP          0
561 #define IOP_TAG_MULTIPLE_COMPONENTS   1
562
563
564 /* Max Supported versions */
565
566 static const guint GIOP_MAJOR =  1;
567 static const guint GIOP_MINOR =  2;
568
569
570 static const int KeyAddr       = 0;
571 static const int ProfileAddr   = 1;
572 static const int ReferenceAddr = 2;
573
574
575
576 static const value_string reply_status_types[] = { 
577    { NO_EXCEPTION, "No Exception" } ,
578    { USER_EXCEPTION, "User Exception" } ,
579    { SYSTEM_EXCEPTION, "System Exception" } ,
580    { LOCATION_FORWARD, "Location Forward" } ,
581    { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
582    { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
583    { 0, NULL }
584 };
585
586
587
588 typedef enum LocateStatusType
589 {
590   UNKNOWN_OBJECT,
591   OBJECT_HERE,
592   OBJECT_FORWARD,
593   OBJECT_FORWARD_PERM,      /* new value for GIOP 1.2 */
594   LOC_SYSTEM_EXCEPTION,     /* new value for GIOP 1.2 */
595   LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
596 }
597 LocateStatusType_t;
598
599 typedef struct LocateReplyHeader
600 {
601   guint32 request_id;
602   guint32 locate_status;
603 }
604 LocateReplyHeader_t;
605
606
607 /*
608  * DATA - complete_request_list 
609  */
610
611 static GList *giop_complete_request_list;
612
613 struct comp_req_list_entry {
614   guint32 fn;                   /* frame number */
615   gchar * operation;            /* echo echoString */
616   giop_sub_handle_t *subh;      /* handle to sub dissector */
617   guint32 reqid;                /* request id */  
618   gchar * repoid;               /* repository ID */
619 };
620
621 typedef struct comp_req_list_entry comp_req_list_entry_t;
622
623
624 /*
625  * DATA - complete_reply_hash
626  *
627  * Maps reply FN to request MFN
628  */
629
630 static int complete_reply_hash_count = 1000; /* storage size for our permanent data */
631                                              /* ie: 1000 entries -- needs tweaking -- FS */
632
633 struct complete_reply_hash_key {
634   guint32 fn;                   /* reply frame number  */
635 };
636
637 struct complete_reply_hash_val {
638   guint32 mfn;                  /* matching frame number (request)  */
639 };
640
641 GHashTable *giop_complete_reply_hash = NULL; /* hash */
642 GMemChunk  *giop_complete_reply_keys = NULL; /* key storage */
643 GMemChunk  *giop_complete_reply_vals = NULL; /* val storage */
644
645
646 /*
647  * DATA - Module Hash stuff to store data from register_giop_user_module
648  *
649  * ie: module (or interface ?) name, and ptr to sub_dissector handle
650  *
651  * With this knowledge, we can call a sub dissector directly, 
652  * by :
653  * 
654  * objkey -> repoid -> sub_dissector via registered module/interface
655  *
656  */
657
658
659 static int giop_module_init_count = 100; /* storage size for our permanent data */
660                                          /* ie: 100 entries -- needs tweaking -- FS */
661
662 struct giop_module_key {
663   gchar *module;                /* module (interface?) name  */
664 };
665
666 struct giop_module_val {
667   giop_sub_handle_t *subh;      /* handle to sub dissector */
668 };
669
670 GHashTable *giop_module_hash = NULL; /* hash */
671 GMemChunk  *giop_module_keys = NULL; /* key storage */
672 GMemChunk  *giop_module_vals = NULL; /* val storage */
673
674
675 /*
676  * DATA - GSList to store list of function (dissector) pointers.
677  * for heuristic dissection.
678  *
679  */
680
681 static GSList *giop_sub_list = NULL;
682
683 /*
684  * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
685  * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
686  *
687  * With this knowledge, we can call a sub dissector directly later
688  * by :
689  * 
690  * objkey -> repoid -> sub_dissector via registered module/interface
691  *
692  * rather than heuristic calls that do not provide operation context.
693  * (unless we pass the RepoID for a given objkey -- hmmm)
694  *
695  */
696
697 /*
698  * Interesting operation list, add more if you want to save
699  * interesting data.
700  */
701
702 static const char  giop_op_resolve[]           = "resolve";
703 static const char  giop_op_bind_new_context[]  = "bind_new_context";
704 static const char  giop_op_bind[]              = "bind";
705
706 /*
707  * Enums  for interesting local operations, that we may need to monitor
708  * with their subsequent replies
709  * 
710  */
711
712 enum giop_op_val {
713   request_resolve_op_val,            /* REQUEST (resolve) to get RepoID etc*/
714   request_bind_new_context_op_val,   /* bind_new_context */
715   request_bind_op_val,               /* bind */
716   request_get_INIT_op_val,           /* finding Nameserver */
717
718 };
719
720
721 /*
722  * hash for mapping object keys onto object namespaces, so
723  * I can call the correct dissector.
724  *
725  *
726  */
727
728 /*
729  * Where did I get the IOR from.
730  */
731
732 enum ior_src {
733   req_res = 0,                  /* REQUEST (resolve) */
734   file,                         /* stringified IOR' in a file */
735
736 };
737
738 typedef enum ior_src ior_src_t;
739
740
741
742 /*
743  * Enums for my lists and hash's 
744  */
745
746 enum collection_data {
747   cd_heuristic_users = 0,
748   cd_module_hash,
749   cd_objkey_hash,
750   cd_complete_request_list,
751   cd_complete_reply_hash
752 };
753
754 typedef enum collection_data collection_data_t;
755
756
757
758 static int giop_objkey_init_count = 100; /* storage size for our permanent data */
759                                          /* ie: 100 entries -- needs tweaking -- FS */
760
761 struct giop_object_key {
762   guint8 *objkey;               /* ptr to object key */
763   guint32 objkey_len;           /* length */
764 };
765
766 struct giop_object_val { 
767   guint8 *repo_id;              /* ptr to Repository ID string */
768   ior_src_t src;                /* where did Iget this IOR from */
769 };
770
771 GHashTable *giop_objkey_hash = NULL; /* hash */
772 GMemChunk  *giop_objkey_keys = NULL; /* key storage */
773 GMemChunk  *giop_objkey_vals = NULL; /* val storage */
774
775
776
777 /*
778  * ------------------------------------------------------------------------------------------+ 
779  *                                 Private helper functions
780  * ------------------------------------------------------------------------------------------+
781  */
782
783
784
785 /*
786  * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
787  */
788
789 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
790   GList * newlist_start;
791   comp_req_list_entry_t * entry = NULL;
792   gchar * opn;
793
794   entry =  g_malloc(sizeof(comp_req_list_entry_t));
795   opn =  g_strdup(op); /* duplicate operation for storage */
796     
797   entry->fn = fn;
798   entry->reqid = reqid;
799   entry->subh = sh;             
800   entry->operation = opn;       
801   entry->repoid = NULL;         /* dont have yet */
802
803   newlist_start = g_list_append (list, entry); /* append */
804
805   return newlist_start;
806 }
807
808
809 /*
810  * Used to find an entry with matching Frame Number FN
811  * in the complete_request_list list.
812  */
813
814 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
815
816   GList * element;              /*  entry in list */
817   comp_req_list_entry_t * entry_ptr = NULL;
818   
819   element = g_list_last(giop_complete_request_list); /* start from  last  */
820   
821   while(element) {                      /* valid list entry */
822     entry_ptr = element->data;  /* grab data pointer */
823     if (entry_ptr->fn == fn) {  /* similar FN  */
824       return entry_ptr;
825     }    
826     element = g_list_previous(element); /* try next previous */
827   }
828   
829   return NULL;                  /* no match so return NULL */
830 }
831
832
833 /*
834  * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
835  *
836  * Call this when you know a FN and matching giop_sub_handle_t and repoid
837  *
838  * This is done in say, try_explicit_dissector for example.
839  *
840  */
841
842 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
843
844   comp_req_list_entry_t * entry = NULL;
845   entry = find_fn_in_list(fn);  /* grab FN data entry */
846
847   if (entry) {
848     entry->subh = sh;           
849     entry->repoid = g_strdup(repoid); /* copy and store */
850
851   }
852 }
853
854
855
856
857 /* giop_complete_reply_hash  "EQUAL" Functions */
858
859 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
860   struct complete_reply_hash_key *mk1 = (struct complete_reply_hash_key *)v;
861   struct complete_reply_hash_key *mk2 = (struct complete_reply_hash_key *)w;
862
863   if (mk1->fn == mk2->fn) {    
864     return 1;
865   }
866
867   return 0;                     /* found  differences */
868 }
869
870 /* giop_complete_reply_hash "HASH" Functions */
871
872 static guint32 complete_reply_hash_fn(gconstpointer v) {
873   guint32 val;          /* init hash value */
874   struct complete_reply_hash_key *key = (struct complete_reply_hash_key *)v;
875
876   val = key->fn;                /* simple and unique */
877
878   return val;
879 }
880
881
882 /*
883  * Insert the FN and MFN together in our complete_reply_hash.
884  */
885
886 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
887
888   struct complete_reply_hash_key key, *new_key;
889   struct complete_reply_hash_val *val = NULL;
890
891   key.fn = fn;
892
893   val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
894
895   if (val) {
896     return;                     /* FN collision */
897   }
898
899   new_key = g_mem_chunk_alloc(giop_complete_reply_keys);
900   new_key->fn = fn;             /* save FN */
901
902   val = g_mem_chunk_alloc(giop_complete_reply_vals);
903   val->mfn = mfn;               /* and MFN */
904   
905   g_hash_table_insert(giop_complete_reply_hash, new_key, val);
906
907 }
908
909 /*
910  * Find the MFN values from a given FN key.
911  * Assumes the complete_reply_hash is already populated.
912  */
913
914 static guint32 get_mfn_from_fn(guint32 fn) {
915
916   struct complete_reply_hash_key key;
917   struct complete_reply_hash_val *val = NULL;
918   guint32 mfn = fn;             /* save */
919
920   key.fn = fn;
921   val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
922
923   if (val) {
924     mfn = val->mfn;             /* grab it */
925   }
926   
927   return mfn;                   /* mfn or fn if not found */
928
929 }
930
931 /*
932  * Attempt to find the MFN for this FN, and return it.
933  * Return MFN if found, or just FN if not. This is
934  * only used when we are building
935  */
936
937 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
938
939   GList * element;              /* last entry in list */
940   comp_req_list_entry_t * entry_ptr = NULL;
941
942   /* Need Some pretty snappy code */
943   
944   /* Loop back from current end of complete_request_list looking for */
945   /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
946
947   /*
948    * As this routine is only called during initial pass of data,
949    * and NOT when a user clicks, it is ok to start from Current
950    * end of complete_request_list when searching for a match.
951    * As that list is bing populated in the same order as FN's
952    * are being read.
953    *
954    * Also, can make check for same reqid more detailed, but I start
955    * with reqid. Could add say port or address checks etc later ??
956    */
957
958
959   element = g_list_last(giop_complete_request_list); /* get last  */
960   
961   while(element) {                      /* valid list entry */
962     entry_ptr = element->data;  /* grab data pointer */
963     if (entry_ptr->reqid == reqid) {    /* similar reqid  */
964       return entry_ptr->fn;     /* return MFN */
965     }    
966     element = g_list_previous(element); /* try next previous */
967   }
968   
969   return fn;                    /* no match so return FN */
970 }
971
972
973 /* Module Hash "EQUAL" Functions */
974
975 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
976   struct giop_module_key *mk1 = (struct giop_module_key *)v;
977   struct giop_module_key *mk2 = (struct giop_module_key *)w;
978   
979   if (!strcmp(mk1->module, mk2->module)) {    
980     return 1;
981   }
982
983   return 0;                     /* found  differences */
984 }
985
986 /* Module Hash "HASH" Functions */
987
988 static guint32 giop_hash_module_hash(gconstpointer v) {
989   
990   int i,len;
991   guint32 val = 0;              /* init hash value */
992
993   struct giop_module_key *key = (struct giop_module_key *)v;
994   
995   /*
996    * Hmm, try this simple hashing scheme for now.
997    * ie: Simple summation, FIX later -- FS
998    *
999    *
1000    */
1001
1002   len = strlen(key->module);
1003
1004   for (i=0; i<len; i++) {
1005     val += (guint8) key->module[i];
1006   }
1007
1008   return val;
1009
1010 }
1011
1012
1013 /*
1014  * ------------------------------------------------------------------------------------------+ 
1015  *                                 Public Utility functions
1016  * ------------------------------------------------------------------------------------------+
1017  */
1018
1019
1020
1021
1022 /*
1023  * Routine to  allow giop users to register their sub dissector function, name, and
1024  * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1025  * value returned from their proto_register_protocol(), so we can enable/disbale it
1026  * through the GUI (edit protocols).
1027  *
1028  * This is used by try_explicit_giop_dissector() to find the
1029  * correct sub-dissector.
1030  *
1031  */
1032
1033 void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
1034
1035   struct giop_module_key module_key, *new_module_key;
1036   struct giop_module_val *module_val = NULL;
1037
1038   module_key.module = module; /*  module name */
1039   
1040   module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1041
1042   if (module_val) {
1043     return;                     /* module name collision */
1044   }
1045   
1046   /* So, passed module name should NOT exist in hash at this point.*/
1047
1048 #if DEBUG    
1049   printf("giop:register_module: Adding Module %s to module hash \n", module);
1050   printf("giop:register_module: Module sub dissector name is %s \n", name);
1051 #endif
1052
1053   new_module_key = g_mem_chunk_alloc(giop_module_keys);
1054   new_module_key->module = module; /* save Module or interface name from IDL */
1055   
1056   module_val = g_mem_chunk_alloc(giop_module_vals);
1057
1058   module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh  */
1059
1060   module_val->subh->sub_name = name;    /* save dissector name */
1061   module_val->subh->sub_fn = sub;       /* save subdissector*/
1062   module_val->subh->sub_proto = sub_proto;      /* save subdissector's proto_XXX value */
1063   
1064   g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1065
1066 }
1067
1068
1069
1070
1071 /* Object Key Hash "EQUAL" Functions */
1072
1073 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1074   struct giop_object_key *v1 = (struct giop_object_key *)v;
1075   struct giop_object_key *v2 = (struct giop_object_key *)w;
1076
1077   if (v1->objkey_len != v2->objkey_len)
1078     return 0;                   /* no match because different length */
1079
1080   /* Now do a byte comaprison */
1081
1082   if (!memcmp(v1->objkey,v2->objkey, v1->objkey_len)) {
1083     return 1;           /* compares ok */
1084   }
1085
1086 #if DEBUG
1087   printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1088 #endif
1089
1090   return 0;                     /* found  differences */
1091 }
1092
1093 /* Object Key Hash "HASH" Functions */
1094
1095 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1096   struct giop_object_key *key = (struct giop_object_key *)v;
1097
1098   guint32 i;
1099   guint32 val = 0;              /* init hash value */
1100
1101
1102   /*
1103    * Hmm, try this simple hashing scheme for now.
1104    * ie: Simple summation
1105    *
1106    *
1107    */
1108
1109 #if DEBUG
1110   printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1111 #endif
1112
1113   for (i=0; i< key->objkey_len; i++) {
1114     val += (guint8) key->objkey[i];
1115   }
1116
1117   return val;
1118
1119 }
1120
1121 /*
1122  * Routine to take an object key octet sequence, and length, and ptr to
1123  * a (null terminated )repository ID string, and store them in the obect key hash.
1124  *
1125  * Blindly Inserts even if it does exist, See TODO at top for reason.
1126  */
1127
1128 static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
1129
1130   struct giop_object_key objkey_key, *new_objkey_key;
1131   struct giop_object_val *objkey_val = NULL;
1132
1133   objkey_key.objkey_len  = len; /*  length  */
1134   objkey_key.objkey  = obj;     /*  object key octet sequence  */
1135
1136   /* Look it up to see if it exists */
1137
1138   objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1139
1140   /* CHANGED -- Same reqid, so abandon old entry */
1141
1142   if (objkey_val) {
1143     g_hash_table_remove(hash, &objkey_key);
1144   }
1145   
1146   /* So, passed key should NOT exist in hash at this point.*/
1147     
1148   new_objkey_key = g_mem_chunk_alloc(giop_objkey_keys);
1149   new_objkey_key->objkey_len = len; /* save it */
1150   new_objkey_key->objkey = (guint8 *) g_memdup(obj,len);        /* copy from object and allocate ptr */
1151     
1152   objkey_val = g_mem_chunk_alloc(giop_objkey_vals);
1153   objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
1154   objkey_val->src = src; /* where IOR came from */
1155
1156
1157 #if DEBUG  
1158   printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash  \n",
1159          objkey_val->repo_id, new_objkey_key->objkey_len);
1160 #endif
1161
1162   g_hash_table_insert(hash, new_objkey_key, objkey_val);
1163
1164 }
1165
1166
1167
1168 /*
1169  * convert an ascii char representing a hex value,
1170  * to a numeric value.
1171  *
1172  * returns value, or -1 if problem.
1173  *
1174  */
1175
1176 static gint8 hex_char_to_val(guchar c){
1177   gint8 retval ;
1178
1179   if (!isxdigit(c)) {
1180     return -1;
1181   }
1182   if (isdigit(c)) {
1183     retval = c - 48;            /* convert digit */
1184     return retval;
1185   }
1186
1187   c = toupper(c);               /* convert to uppercase */
1188   if (c >= 'A' && c <= 'F') {
1189     retval = c - 55;
1190     return retval;
1191   } 
1192   else {
1193     return -1;
1194   }
1195
1196 }
1197
1198 /*
1199  * Convert from  stringified IOR of the kind IOR:af4f7e459f....
1200  * to an IOR octet sequence.
1201  *
1202  * User must free buffer.
1203  *
1204  * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1205  * grab repoid etc for our objkey hash. 
1206  *
1207  */
1208
1209 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1210   gint8 tmpval_lsb;
1211   gint8 tmpval_msb;
1212   gint8 tmpval;         /* complete value */
1213   guint32 i;
1214
1215   *out = g_new0(guint8, in_len); /* allocate buffer */
1216
1217   if (*out == NULL) {
1218     return 0;
1219   }
1220
1221   /* skip past IOR:  and convert character pairs to guint8 */
1222
1223   for (i=4; i<in_len-1; i+=2) {
1224     if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1225       
1226       if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1227         g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1228
1229       }
1230       
1231       if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1232         g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1233       }
1234       
1235       tmpval = tmpval_msb << 4;
1236       tmpval += tmpval_lsb;
1237       (*out)[(i-4)/2] = (guint8) tmpval;
1238
1239     }
1240     else {
1241       /* hmm  */
1242       break;
1243     }
1244     
1245   }
1246
1247   return (i-4)/2;               /* length  */
1248
1249 }
1250
1251
1252
1253 /*
1254  * Simple getline, copied from somewhere :)
1255  *
1256  */
1257
1258 static int getline(FILE *fp, gchar *line, int maxlen) {
1259
1260   if (fgets(line,maxlen,fp) == NULL)
1261     return 0;
1262   else
1263     return strlen(line);
1264
1265 }
1266
1267
1268 /* 
1269  * Read a list of stringified IOR's from a named file, convert to IOR's
1270  * and store in object key hash
1271  */
1272
1273 static void read_IOR_strings_from_file(gchar *name, int max_iorlen) {
1274   guchar *buf;                  /* NOTE reused for every line */
1275   int len;
1276   int ior_val_len;              /* length after unstringifying. */
1277   FILE *fp;             
1278   guint8 *out;                  /* ptr to unstringified IOR */
1279   tvbuff_t *tvb;                /* temp tvbuff for dissectin IORs */
1280   guint32 my_offset = 0;
1281   gboolean stream_is_big_endian;
1282
1283
1284   fp = fopen(name,"r"); /* open read only */
1285
1286   if (fp == NULL) {
1287     if (errno == EACCES)
1288       fprintf(stderr, "Error opening file IOR.txt for reading: %s\n",strerror(errno));
1289     return;
1290   }
1291
1292   buf = g_malloc0(max_iorlen+1);        /* input buf */
1293
1294   while ((len = getline(fp,buf,max_iorlen+1)) > 0) {
1295     my_offset = 0;              /* reset for every IOR read */
1296
1297     ior_val_len = string_to_IOR(buf,len,&out);  /* convert */
1298
1299     if(ior_val_len>0) {
1300     
1301       /* Combination of tvb_new() and tvb_set_real_data().
1302          Can throw ReportedBoundsError.
1303
1304          XXX - can it throw an exception in this case?  If so, we
1305          need to catch it and clean up, but we really shouldn't allow
1306          it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
1307          exception. */
1308
1309       tvb =  tvb_new_real_data(out, ior_val_len, ior_val_len);
1310
1311       stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1312       decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1313
1314       tvb_free(tvb);
1315
1316     }
1317
1318     g_free(out);
1319
1320   }
1321
1322   fclose(fp);                   /* be nice */
1323
1324   g_free(buf);
1325 }
1326
1327
1328
1329 /*
1330  * Init routine, setup our request hash stuff, or delete old ref's
1331  *
1332  * Cannot setup the module hash here as my init() may not be called before
1333  * users start registering. So I will move the module_hash stuff to
1334  * proto_register_giop, as is done with packet-rpc
1335  *
1336  *
1337  *
1338  * Also, setup our objectkey/repoid hash here.
1339  *
1340  */
1341
1342 static void giop_init(void) {
1343
1344
1345   /*
1346    * Create objkey/repoid  hash, use my "equal" and "hash" functions.
1347    * 
1348    */
1349
1350   if (giop_objkey_hash)
1351     g_hash_table_destroy(giop_objkey_hash);
1352   if (giop_objkey_keys)
1353     g_mem_chunk_destroy(giop_objkey_keys);
1354   if (giop_objkey_vals)
1355     g_mem_chunk_destroy(giop_objkey_vals);
1356
1357
1358   /*
1359    * Create hash, use my "equal" and "hash" functions.
1360    * 
1361    */
1362
1363   giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1364
1365   giop_objkey_keys = g_mem_chunk_new("giop_objkey_keys",
1366                                          sizeof(struct giop_object_key),
1367                                          giop_objkey_init_count * sizeof(struct giop_object_key), 
1368                                          G_ALLOC_AND_FREE);
1369
1370   giop_objkey_vals = g_mem_chunk_new("giop_objkey_vals", 
1371                                          sizeof(struct giop_object_val),
1372                                          giop_objkey_init_count * sizeof(struct giop_object_val), 
1373                                          G_ALLOC_AND_FREE);
1374
1375
1376   /*
1377    * Create complete_reply_hash, use my "equal" and "hash" functions.
1378    * 
1379    */
1380
1381   if (giop_complete_reply_hash)
1382     g_hash_table_destroy(giop_complete_reply_hash);
1383   if (giop_complete_reply_keys)
1384     g_mem_chunk_destroy(giop_complete_reply_keys);
1385   if (giop_complete_reply_vals)
1386     g_mem_chunk_destroy(giop_complete_reply_vals);
1387
1388
1389   /*
1390    * Create hash, use my "equal" and "hash" functions.
1391    * 
1392    */
1393
1394   giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1395
1396   giop_complete_reply_keys = g_mem_chunk_new("giop_complete_reply_keys",
1397                                          sizeof(struct complete_reply_hash_key),
1398                                          complete_reply_hash_count * sizeof(struct complete_reply_hash_key), 
1399                                          G_ALLOC_AND_FREE);
1400
1401   giop_complete_reply_vals = g_mem_chunk_new("giop_complete_reply_vals", 
1402                                          sizeof(struct complete_reply_hash_val),
1403                                          complete_reply_hash_count * sizeof(struct complete_reply_hash_val), 
1404                                          G_ALLOC_AND_FREE);
1405
1406
1407   
1408   read_IOR_strings_from_file("IOR.txt", 600); /* testing */
1409
1410
1411 }
1412
1413
1414 /* 
1415  * Insert an entry in the GIOP Heuristic User table.
1416  * Uses a GList.
1417  * Uses giop_sub_handle_t to wrap giop user info.
1418  *
1419  */
1420     
1421 void register_giop_user(giop_sub_dissector_t *sub, gchar *name, int sub_proto) {
1422
1423   giop_sub_handle_t *subh;
1424   
1425   subh = g_malloc(sizeof (giop_sub_handle_t));
1426
1427   subh->sub_name = name;
1428   subh->sub_fn = sub;
1429   subh->sub_proto = sub_proto;  /* proto_XXX from sub dissectors's proto_register_protocol() */
1430
1431   giop_sub_list = g_slist_append (giop_sub_list, subh);
1432  
1433 }
1434
1435
1436 /*
1437  * Lookup an object key in our object key hash, and return the corresponding
1438  * Repo Id.
1439  *
1440  */
1441
1442 static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
1443
1444   struct giop_object_key objkey_key;
1445   struct giop_object_val *objkey_val = NULL;
1446
1447   objkey_key.objkey_len  = len; /*  length  */
1448   objkey_key.objkey  = obj;     /*  object key octet sequence  */
1449
1450   /* Look it up to see if it exists */
1451
1452   objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1453
1454   if (objkey_val) {
1455 #if DEBUG
1456     printf("Lookup of object key returns  RepoId = %s \n",objkey_val->repo_id );
1457 #endif
1458     return objkey_val->repo_id; /* found  */
1459   }
1460
1461 #if DEBUG    
1462   printf("FAILED Lookup of object key \n" );
1463 #endif
1464   
1465   return NULL;                  /* not  found */
1466 }
1467
1468
1469
1470 /*
1471  * Extract top level module/interface from repoid 
1472  *
1473  * eg from -  "IDL:Echo/interface1:1.0"
1474  * get "Echo"
1475  *
1476  * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1477  * get linux.org/Penguin/Teeth
1478  * 
1479  *
1480  * User must free returned ptr after use.
1481  *
1482  * TODO -- generalize for other Repoid encodings
1483  */
1484
1485 static gchar * get_modname_from_repoid(gchar *repoid) {
1486
1487   gchar *modname = NULL;
1488   gchar *saved_repoid = NULL;
1489   gchar c = 'a';
1490   guint8 stop_mod;              /* Index of last character of modname in Repoid  */
1491   guint8 start_mod = 4;         /* Index where Module name starts in repoid */
1492   int i;
1493
1494   saved_repoid = g_strdup(repoid); /* make a copy */
1495
1496   /* Must start with IDL: , otherwise I get confused */
1497
1498   if (g_strncasecmp("IDL:",repoid,4))
1499     return NULL;
1500
1501   /* Looks like a RepoID to me, so get Module or interface name */
1502
1503   /* TODO -- put some code here to get Module name */
1504
1505   for(i=4; c != '\0'; i++) {
1506     c = repoid[i];
1507     stop_mod = i;               /* save */
1508     if (c == ':' )              /* delimiters */
1509       break;
1510     
1511   }
1512
1513   /* Now create a new string based on start and stop and \0 */
1514   
1515   modname = g_strndup(repoid+4, stop_mod - start_mod);
1516     
1517   return modname;
1518   
1519 }
1520
1521 /*
1522  * DEBUG CODE
1523  *
1524  */
1525
1526
1527 #if DEBUG
1528
1529 /*
1530  * Display a "module" hash entry
1531  */
1532
1533 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1534
1535   struct giop_module_val *mv = (struct giop_module_val *) val;
1536   struct giop_module_key *mk = (struct giop_module_key *) key;
1537
1538   printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1539   
1540   return;
1541
1542 }
1543
1544 /*
1545  * Display a "complete_reply " hash entry
1546  */
1547
1548 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1549
1550   struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1551   struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1552
1553   printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1554   
1555   return;
1556
1557 }
1558
1559
1560 /*
1561  * Display an "objkey" hash entry
1562  */
1563
1564 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1565   guint32 i;
1566   struct giop_object_val *mv = (struct giop_object_val *) val;
1567   struct giop_object_key *mk = (struct giop_object_key *) key;
1568
1569
1570   printf("giop:objkey: Key->objkey_len = %u,  Key->objkey ",  mk->objkey_len);
1571
1572   for (i=0; i<mk->objkey_len; i++) {
1573     printf("%.2x ", mk->objkey[i]);
1574   }
1575
1576   /*
1577    * If read from file, mark it as such..
1578    */
1579
1580   if(mv->src == 0) {
1581     printf(", Repo ID = %s \n", mv->repo_id);
1582   }
1583   else {
1584     printf(", Repo ID = %s , (file) \n", mv->repo_id);    
1585   }
1586   
1587   return;
1588
1589 }
1590
1591 /*
1592  * Display all giop_sub_list (GSList) entries
1593  */
1594
1595 static void display_heuristic_user_list() {
1596   int i;
1597   int len;
1598   giop_sub_handle_t *subh;      /* handle */
1599   
1600   /* Get length of list */
1601   len = g_slist_length(giop_sub_list); /* find length */
1602
1603   if (len == 0)
1604     return;
1605
1606   for (i=0; i<len; i++) {
1607     subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1608     printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1609   }
1610   
1611 }
1612
1613 /*
1614  * Display all complete_request_list (GList) entries
1615  */
1616
1617 static void display_complete_request_list() {
1618   int i;
1619   int len;
1620   comp_req_list_entry_t *entry;
1621   
1622   /* Get length of list */
1623   len = g_list_length(giop_complete_request_list); /* find length */
1624
1625   if (len == 0)
1626     return;
1627
1628   for (i=0; i<len; i++) {
1629     entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1630     printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn, 
1631            entry->reqid,entry->operation, entry->repoid);
1632   }
1633   
1634 }
1635
1636
1637
1638
1639 /* Dump Hash/List contents 
1640  *
1641  * collection_type specifies the list or hash to dump
1642  *
1643  */
1644
1645 static void giop_dump_collection(collection_data_t collection_type) {
1646
1647   switch(collection_type) {
1648   case cd_heuristic_users:
1649     printf("+----------------------------------------------+ \n");
1650     printf("+-------------- Heuristic User (Begin) --------+ \n");
1651     printf("+----------------------------------------------+ \n");
1652
1653     display_heuristic_user_list();
1654
1655     printf("+----------------------------------------------+ \n");
1656     printf("+-------------- Heuristic User (End) ----------+ \n");
1657     printf("+----------------------------------------------+ \n");
1658
1659     break;
1660
1661   case cd_complete_request_list:
1662     printf("+----------------------------------------------+ \n");
1663     printf("+------------- Complete Request List (Begin) --+ \n");
1664     printf("+----------------------------------------------+ \n");
1665
1666     display_complete_request_list();
1667
1668     printf("+----------------------------------------------+ \n");
1669     printf("+------------ Complete Request List (End) -----+ \n");
1670     printf("+----------------------------------------------+ \n");
1671
1672     break;
1673
1674   case cd_module_hash:
1675     printf("+----------------------------------------------+ \n");
1676     printf("+-------------- Module (Begin) ----------------+ \n");
1677     printf("+----------------------------------------------+ \n");
1678
1679     g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1680
1681     printf("+----------------------------------------------+ \n");
1682     printf("+-------------- Module ( End) -----------------+ \n");
1683     printf("+----------------------------------------------+ \n\n");
1684
1685     break;
1686
1687   case cd_objkey_hash:
1688     printf("+----------------------------------------------+ \n");
1689     printf("+-------------- Objkey (Begin) ----------------+ \n");
1690     printf("+----------------------------------------------+ \n");
1691
1692     g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1693
1694     printf("+----------------------------------------------+ \n");
1695     printf("+-------------- Objkey (End) ------------------+ \n");
1696     printf("+----------------------------------------------+ \n\n");
1697   
1698     break;
1699
1700   case cd_complete_reply_hash:
1701     printf("+----------------------------------------------+ \n");
1702     printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1703     printf("+----------------------------------------------+ \n");
1704
1705     g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1706
1707     printf("+----------------------------------------------+ \n");
1708     printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1709     printf("+----------------------------------------------+ \n");
1710
1711     break;
1712     
1713   default:
1714
1715     printf("giop: giop_dump_collection: Unknown type   \n");
1716
1717   }
1718
1719
1720 }
1721
1722
1723 #endif /* DEBUG */
1724
1725 /*
1726  * Loop through all  subdissectors, and call them until someone
1727  * answers (returns TRUE). This function then returns TRUE, otherwise
1728  * it return FALSE
1729  *
1730  * But skip a subdissector if it has been disabled in GUI "edit protocols".
1731  */
1732
1733 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1734                 MessageHeader *header, gchar *operation  ) {
1735
1736   int i,len;
1737   gboolean res = FALSE;         /* result of calling a heuristic sub dissector */
1738   giop_sub_handle_t *subh = NULL; 
1739   const char *saved_proto;
1740
1741   len = g_slist_length(giop_sub_list); /* find length */
1742
1743   if (len == 0)
1744     return FALSE;
1745
1746   saved_proto = pinfo->current_proto;
1747   for (i=0; i<len; i++) {
1748     subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1749
1750     if (proto_is_protocol_enabled(subh->sub_proto)) {
1751       pinfo->current_proto =
1752         proto_get_protocol_short_name(subh->sub_proto);
1753       res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1754       if (res) {
1755         pinfo->current_proto = saved_proto;
1756         return TRUE;            /* found one, lets return */
1757       }  
1758     } /* protocol_is_enabled */
1759   } /* loop */
1760
1761   if (check_col (pinfo->cinfo, COL_PROTOCOL))
1762       col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
1763
1764   pinfo->current_proto = saved_proto;
1765   return res;                   /* result */
1766
1767 }
1768
1769
1770 /*
1771  * Find the matching repoid in the module hash and call
1772  * the dissector function if offset exists.
1773  * 
1774  *
1775  * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors 
1776  * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth". 
1777  *
1778  *
1779  *
1780  */
1781
1782 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1783                                             MessageHeader *header, gchar *operation, gchar *repoid ) {
1784
1785   giop_sub_handle_t *subdiss = NULL; /* handle */
1786   gboolean res = FALSE;
1787   gchar *modname = NULL;
1788   struct giop_module_key module_key;
1789   struct giop_module_val *module_val = NULL;
1790   const char *saved_proto;
1791
1792
1793   /*
1794    * Get top level module/interface from complete repoid 
1795    */
1796
1797   modname = get_modname_from_repoid(repoid); 
1798   if (modname == NULL) {
1799     return res;                 /* unknown module name */
1800   }
1801
1802
1803   /* Search for Module or interface name */
1804
1805   module_key.module = modname; /*  module name */
1806   module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1807
1808   if (module_val == NULL) {
1809     return res;                 /* module not registered */
1810   }
1811   
1812   subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1813
1814   if (subdiss) {
1815     /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1816     /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1817     /* but only if user not clicking */
1818
1819     if (!pinfo->fd->flags.visited)
1820       add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1821
1822
1823     /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1824
1825     if (tvb_offset_exists(tvb, *offset)) {   
1826 #if DEBUG  
1827       printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name  , modname);
1828 #endif
1829
1830       if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1831
1832         saved_proto = pinfo->current_proto;
1833         pinfo->current_proto =
1834           proto_get_protocol_short_name(subdiss->sub_proto);
1835         res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1836         pinfo->current_proto = saved_proto;
1837
1838       } /* protocol_is_enabled */
1839     } /* offset exists */
1840   } /* subdiss */
1841   
1842   return res;                   /* return result */
1843 }
1844
1845
1846
1847 /* Take in an array of char and create a new string.
1848  * Replace non-printable characters with periods.
1849  *
1850  * The array may contain \0's so dont use strdup
1851  * The string is \0 terminated, and thus longer than
1852  * the initial sequence. 
1853  * Caller must free the new string.
1854  */
1855
1856 static gchar * make_printable_string (gchar *in, guint32 len) {
1857   guint32 i = 0;
1858   gchar *print_string = NULL;
1859
1860   print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1861   memcpy(print_string, in, len);        /* and make a copy of input data */
1862   
1863   for(i=0; i < len; i++) {
1864     if( !isprint( (unsigned char)print_string[i] ) ) 
1865       print_string[i] = '.';
1866   }
1867
1868   return print_string;          /* return ptr */
1869 }
1870
1871 /* Determine the byte order from the GIOP MessageHeader */
1872
1873 gboolean is_big_endian (MessageHeader * header) {
1874   gboolean big_endian = FALSE;
1875
1876   switch (header->GIOP_version.minor) {
1877   case 2:
1878   case 1:
1879     if (header->flags & 0x01)
1880       big_endian = FALSE;
1881     else
1882       big_endian = TRUE;
1883     break;
1884   case 0:
1885     if (header->flags)
1886       big_endian = FALSE;
1887     else
1888       big_endian = TRUE;
1889     break;
1890   default:
1891     break;
1892   }
1893   return big_endian;
1894 }
1895
1896
1897
1898 /* 
1899  * Calculate new offset, based on the current offset, and user supplied 
1900  * "offset delta" value, and the alignment requirement.
1901  *
1902  *
1903  *
1904  * eg: Used for GIOP 1.2 where Request and Reply bodies are 
1905  *     aligned on 8 byte boundaries.
1906  */
1907
1908 static void set_new_alignment(int *offset, int delta, int  alignment) {
1909
1910   while( ( (*offset + delta) % alignment) != 0)
1911           ++(*offset);
1912
1913
1914 }
1915
1916
1917
1918 /*
1919  * ------------------------------------------------------------------------------------------+ 
1920  *                                 Public get_CDR_xxx functions.
1921  * ------------------------------------------------------------------------------------------+
1922  */
1923
1924
1925
1926 /*
1927  * Gets data of type any. This is encoded as a TypeCode
1928  * followed by the encoded value.
1929  */
1930
1931 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
1932                  gboolean stream_is_big_endian, int boundary,
1933                  MessageHeader * header ) {
1934   
1935   guint32  TCKind;    /* TypeCode */
1936
1937   /* get TypeCode of any */
1938   TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1939
1940   /* dissect data of type TCKind */
1941   dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1942 }
1943
1944
1945 /* Copy a 1 octet sequence from the tvbuff 
1946  * which represents a boolean value, and convert
1947  * it to a boolean value.
1948  * Offset is then incremented by 1, to indicate the 1 octet which
1949  * has been processed.
1950  */
1951
1952 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1953   guint8 val;
1954
1955   val = tvb_get_guint8(tvb, *offset); /* easy */
1956   (*offset)++;
1957   return val;
1958 }
1959
1960 /* Copy a 1 octet sequence from the tvbuff 
1961  * which represents a char, and convert
1962  * it to an char value.
1963  * offset is then incremented by 1, to indicate the 1 octet which
1964  * has been processed.
1965  */
1966
1967 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1968   guint8 val;
1969
1970   val = tvb_get_guint8(tvb, *offset); /* easy */
1971   (*offset)++;
1972   return val;
1973 }
1974
1975
1976
1977 /* 
1978  * Floating Point Data Type double IEEE 754-1985 
1979  *
1980  * Copy an 8 octet sequence from the tvbuff 
1981  * which represents a double value, and convert
1982  * it to a double value, taking into account byte order.
1983  * offset is first incremented so that it falls on a proper alignment
1984  * boundary for double values.
1985  * offset is then incremented by 8, to indicate the 8 octets which
1986  * have been processed.
1987  */
1988
1989 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1990
1991   gdouble val;
1992
1993   /* double values must be aligned on a 8 byte boundary */
1994
1995   while( ( (*offset + boundary) % 8) != 0)
1996           ++(*offset);
1997
1998   val = (stream_is_big_endian) ? tvb_get_ntohieee_double (tvb, *offset) :
1999                                  tvb_get_letohieee_double (tvb, *offset);
2000
2001   *offset += 8;
2002   return val;
2003
2004 }
2005
2006
2007 /* Copy a 4 octet sequence from the tvbuff 
2008  * which represents an enum value, and convert
2009  * it to an enum value, taking into account byte order.
2010  * offset is first incremented so that it falls on a proper alignment
2011  * boundary for an enum (4)
2012  * offset is then incremented by 4, to indicate the 4 octets which
2013  * have been processed.
2014  *
2015  * Enum values are encoded as unsigned long.
2016  */
2017
2018
2019 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2020
2021   return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2022
2023 }
2024
2025
2026 /*
2027  * Copy an octet sequence from the tvbuff
2028  * which represents a Fixed point decimal type, and create a string representing
2029  * a Fixed point decimal type. There are no alignment restrictions.
2030  * Size and scale of fixed decimal type is determined by IDL.
2031  * 
2032  * digits - IDL specified number of "digits" for this fixed type
2033  * scale  - IDL specified "scale" for this fixed type
2034  *
2035  *
2036  * eg: typedef fixed <5,2> fixed_t;
2037  *     could represent numbers like 123.45, 789.12, 
2038  *
2039  *
2040  * As the fixed type could be any size, I will not try to fit it into our
2041  * simple types like gdouble or glong etc. I will just create a string buffer holding
2042  * a  representation (after scale is applied), and with a decimal point or zero padding
2043  * inserted at the right place if necessary. The string is null terminated
2044  *
2045  * so string may look like 
2046  *
2047  *
2048  *  "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2049  *
2050  * According to spec, digits <= 31
2051  * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2052  * or <4,0> ?
2053  *
2054  * User must remember to free the buffer
2055  *
2056  */
2057
2058
2059 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2060
2061   guint8 sign;                  /* 0x0c is positive, 0x0d is negative */
2062   guint32 i ;                   /* loop */
2063   guint32 slen;                 /* number of bytes to hold digits + extra 0's if scale <0 */
2064                                 /* this does not include sign, decimal point and \0 */
2065   guint32 sindex = 0;           /* string index */
2066   gchar *tmpbuf;                /* temp buff, holds string without scaling */
2067   guint8 tval;                  /* temp val storage */
2068
2069   /*
2070    * how many bytes to hold digits and scale (if scale <0) 
2071    *
2072    * eg: fixed <5,2> = 5 digits
2073    *     fixed <5,-2> = 7 digits (5 + 2 added 0's)
2074    */
2075
2076 #if DEBUG
2077     printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2078 #endif
2079
2080   if (scale <0) {
2081     slen = digits - scale;      /* allow for digits + padding 0's for negative scal */
2082   } else {
2083     slen = digits;              /*  digits */
2084   }
2085
2086 #if DEBUG
2087     printf("giop:get_CDR_fixed(): slen =  %.2x \n", slen);
2088 #endif
2089   
2090   tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */ 
2091
2092   /*
2093    * Register a cleanup function in case on of our tvbuff accesses
2094    * throws an exception. We need to clean up tmpbuf.
2095    */
2096   CLEANUP_PUSH(g_free, tmpbuf);
2097
2098   /* If even , grab 1st dig */
2099
2100   if (!(digits & 0x01)) {
2101     tval = get_CDR_octet(tvb,offset);
2102 #if DEBUG
2103     printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2104 #endif
2105     tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2106     sindex++;
2107   }
2108
2109   /*
2110    * Loop, but stop BEFORE we hit last digit and sign 
2111    * if digits = 1 or 2, then this part is skipped 
2112    */
2113
2114   if (digits>2) {
2115     for(i=0; i< ((digits-1)/2 ); i++) {
2116       tval = get_CDR_octet(tvb,offset);
2117 #if DEBUG
2118       printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2119 #endif
2120       
2121       tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2122       sindex++;
2123       tmpbuf[sindex] = (tval & 0x0f)  + 0x30; /* convert bot nibble to ascii */
2124       sindex++;
2125       
2126     }
2127   } /* digits > 3 */
2128
2129 #if DEBUG
2130     printf("giop:get_CDR_fixed(): before last digit \n");
2131 #endif
2132   
2133
2134   /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2135
2136     tval = get_CDR_octet(tvb,offset);
2137 #if DEBUG
2138     printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2139 #endif
2140     tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2141     sindex++;
2142
2143     sign = tval & 0x0f; /* get sign */
2144
2145     /* So now, we have all digits in an array, and the sign byte 
2146      * so lets generate a printable string, taking into account the scale
2147      * and sign values.
2148      */
2149  
2150     sindex = 0;                         /* reset */
2151     *seq = g_new0(gchar, slen + 3);     /* allocate temp buffer , including space for sign, decimal point and 
2152                                          * \0 -- TODO check slen is reasonable first */
2153 #if DEBUG
2154     printf("giop:get_CDR_fixed(): sign =  %.2x \n", sign);
2155 #endif                                  
2156     
2157     switch(sign) {
2158     case 0x0c:
2159       (*seq)[sindex] = '+';     /* put sign in first string position */
2160       break;                    
2161     case 0x0d:
2162       (*seq)[sindex] = '-';
2163       break;
2164     default:
2165       g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2166       (*seq)[sindex] = '*';     /* flag as sign unkown */
2167       break;
2168     }
2169
2170     sindex++;
2171
2172     /* Add decimal point or padding 0's, depending if scale is positive or
2173      * negative, respectively
2174      */
2175
2176     if (scale>0) {
2177       for (i=0; i<digits-scale; i++) {
2178         (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */       
2179         sindex++;
2180       }
2181       
2182       (*seq)[sindex] = '.'; /* decimal point */ 
2183       sindex++;
2184       
2185       for (i=digits-scale; i<digits; i++) {
2186         (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */    
2187         sindex++;
2188       }
2189
2190       (*seq)[sindex] = '\0'; /* string terminator */    
2191
2192     } else {
2193
2194       /* negative scale, dump digits and  pad out with 0's */
2195
2196       for (i=0; i<digits-scale; i++) {
2197         if (i<digits) {
2198           (*seq)[sindex] = tmpbuf[i]; /* save digits */ 
2199         } else {
2200           (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */       
2201         }
2202         sindex++;
2203       }
2204
2205       (*seq)[sindex] = '\0'; /* string terminator */    
2206       
2207     }
2208
2209     /*
2210      * We're done with tmpbuf, so we can call the cleanup handler to free
2211      * it, and then pop the cleanup handler.
2212      */
2213     CLEANUP_CALL_AND_POP;
2214     
2215 #if DEBUG
2216     printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2217 #endif
2218
2219     return; 
2220
2221 }
2222
2223
2224
2225 /*
2226  * Floating Point Data Type float IEEE 754-1985 
2227  * 
2228  * Copy an 4 octet sequence from the tvbuff 
2229  * which represents a float value, and convert
2230  * it to a float value, taking into account byte order.
2231  * offset is first incremented so that it falls on a proper alignment
2232  * boundary for float values.
2233  * offset is then incremented by 4, to indicate the 4 octets which
2234  * have been processed.
2235  */
2236
2237 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2238   
2239   gfloat val;
2240   
2241   /* float values must be aligned on a 4 byte boundary */
2242
2243   while( ( (*offset + boundary) % 4) != 0)
2244     ++(*offset);
2245
2246   val = (stream_is_big_endian) ? tvb_get_ntohieee_float (tvb, *offset) :
2247                                  tvb_get_letohieee_float (tvb, *offset);
2248
2249   *offset += 4;
2250   return val;
2251
2252 }
2253
2254
2255 /*
2256  * Decode an Interface type, and display it on the tree.
2257  */
2258
2259 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, 
2260                        gboolean stream_is_big_endian, int boundary) {
2261
2262
2263   decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2264   
2265   return;
2266 }
2267
2268
2269 /* Copy a 4 octet sequence from the tvbuff 
2270  * which represents a signed long value, and convert
2271  * it to an signed long vaule, taking into account byte order.
2272  * offset is first incremented so that it falls on a proper alignment
2273  * boundary for long values.
2274  * offset is then incremented by 4, to indicate the 4 octets which
2275  * have been processed.
2276  */
2277
2278 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2279
2280   gint32 val;
2281
2282   /* unsigned long values must be aligned on a 4 byte boundary */
2283   while( ( (*offset + boundary) % 4) != 0)
2284           ++(*offset);
2285
2286   val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2287                                  tvb_get_letohl (tvb, *offset);
2288
2289   *offset += 4; 
2290   return val; 
2291 }
2292
2293 /*
2294  * Decode an Object type, and display it on the tree.
2295  */
2296
2297 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, 
2298                     gboolean stream_is_big_endian, int boundary) {
2299   
2300   decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2301   
2302   return;
2303 }
2304
2305
2306 /* Copy a 1 octet sequence from the tvbuff 
2307  * which represents a octet, and convert
2308  * it to an octet value.
2309  * offset is then incremented by 1, to indicate the 1 octet which
2310  * has been processed.
2311  */
2312
2313 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2314   guint8 val;
2315
2316   val = tvb_get_guint8(tvb, *offset); /* easy */
2317   (*offset)++;
2318   return val;
2319 }
2320
2321
2322 /* Copy a sequence of octets from the tvbuff.
2323  * Caller of this function must remember to free the 
2324  * array pointed to by seq.
2325  * This function also increments offset by len. 
2326  */
2327
2328 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, guint32 len) {
2329
2330   /*
2331    * Make sure that the entire sequence of octets is in the buffer before
2332    * allocating the buffer, so that we don't have to worry about freeing
2333    * the buffer, and so that we don't try to allocate a buffer bigger
2334    * than the data we'll actually be copying, and thus don't run the risk
2335    * of crashing if the buffer is *so* big that we fail to allocate it
2336    * and "g_new0()" aborts.
2337    */
2338   tvb_ensure_bytes_exist(tvb, *offset, len);
2339
2340   /*
2341    * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2342    * do what we do now, and null-terminate the string (which also means
2343    * we don't need to zero out the entire allocation, just the last byte)?
2344    */
2345   *seq = g_new0(gchar, len + 1);
2346   tvb_memcpy( tvb, *seq, *offset, len);
2347   *offset += len;
2348 }
2349
2350
2351 /* Copy a 2 octet sequence from the tvbuff 
2352  * which represents a signed short value, and convert
2353  * it to a signed short value, taking into account byte order.
2354  * offset is first incremented so that it falls on a proper alignment
2355  * boundary for short values.
2356  * offset is then incremented by 2, to indicate the 2 octets which
2357  * have been processed.
2358  */
2359
2360 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2361
2362   gint16 val;
2363
2364   /* short values must be aligned on a 2 byte boundary */
2365   while( ( (*offset + boundary) % 2) != 0)
2366           ++(*offset);
2367
2368   val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2369                                  tvb_get_letohs (tvb, *offset);
2370
2371   *offset += 2; 
2372   return val; 
2373 }
2374
2375
2376
2377 /* Copy an octet sequence from the tvbuff 
2378  * which represents a string, and convert
2379  * it to an string value, taking into account byte order.
2380  * offset is first incremented so that it falls on a proper alignment
2381  * boundary for string values. (begins with an unsigned long LI)
2382  *
2383  * String sequence is copied to a  buffer "seq". This must
2384  * be freed by the calling program.
2385  * offset is then incremented, to indicate the  octets which
2386  * have been processed.
2387  *
2388  * returns number of octets in the sequence
2389  *
2390  * Note: This function only supports single byte encoding at the
2391  *       moment until I get a handle on multibyte encoding etc.
2392  *
2393  */
2394
2395
2396 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian, 
2397                        int boundary ) {
2398   
2399   guint32 slength;
2400
2401   slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2402
2403 #if 0
2404   (*offset)++;                  /* must step past \0 delimiter */
2405 #endif
2406   
2407   if (slength > 0) {
2408     get_CDR_octet_seq(tvb, seq, offset, slength);
2409   } else {
2410     *seq = g_strdup("");        /* zero-length string */
2411   }
2412
2413   return slength;               /* return length */
2414
2415 }
2416
2417 /* Process a sequence of octets that represent the 
2418  * Pseudo Object Type "TypeCode". Typecodes are used for example,
2419  * by "Any values". 
2420  * This function also increments offset to the correct position.
2421  *
2422  * It will parse the TypeCode and output data to the "tree" provided
2423  * by the user
2424  *
2425  * It returns a guint32 representing a TCKind value. 
2426  */
2427
2428 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
2429                          gboolean stream_is_big_endian, int boundary,
2430                          MessageHeader * header ) {
2431   guint32 val;
2432
2433   gint16  s_octet2; /* signed int16 */
2434   guint16 u_octet2; /* unsigned int16 */
2435   guint32 u_octet4; /* unsigned int32 */
2436
2437   val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2438   if (tree) {
2439     proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2440                         *offset-sizeof(val),4,val);
2441   }
2442
2443   /* Grab the data according to Typecode Table - Corba Chapter 15 */
2444
2445   switch (val) {
2446   case tk_null: /* empty parameter list */
2447     break;
2448   case tk_void: /* empty parameter list */
2449     break;
2450   case tk_short: /* empty parameter list */
2451     break;
2452   case tk_long: /* empty parameter list */
2453     break;
2454   case tk_ushort: /* empty parameter list */
2455     break;
2456   case tk_ulong: /* empty parameter list */
2457     break;
2458   case tk_float: /* empty parameter list */
2459     break;
2460   case tk_double: /* empty parameter list */
2461     break;
2462   case tk_boolean: /* empty parameter list */
2463     break;
2464   case tk_char: /* empty parameter list */
2465     break;
2466   case tk_octet: /* empty parameter list */
2467     break;
2468   case tk_any: /* empty parameter list */
2469     break;
2470   case tk_TypeCode: /* empty parameter list */
2471     break;
2472   case tk_Principal: /* empty parameter list */
2473     break;
2474   case tk_objref: /* complex parameter list */
2475     dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary);
2476     break;
2477   case tk_struct: /* complex parameter list */
2478     dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2479     break;
2480   case tk_union: /* complex parameter list */
2481     dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2482     break;
2483   case tk_enum: /* complex parameter list */
2484     dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary);
2485     break;
2486
2487   case tk_string: /* simple parameter list */
2488     u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2489     if (tree) {
2490       proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2491                           *offset-sizeof(u_octet4),4,u_octet4);
2492     }
2493     break;
2494
2495   case tk_sequence: /* complex parameter list */
2496     dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2497     break;
2498   case tk_array: /* complex parameter list */
2499     dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2500     break;
2501   case tk_alias: /* complex parameter list */
2502     dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2503     break;
2504   case tk_except: /* complex parameter list */
2505     dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2506     break;
2507   case tk_longlong: /* empty parameter list */
2508     break;
2509   case tk_ulonglong: /* empty parameter list */
2510     break;
2511   case tk_longdouble: /* empty parameter list */
2512     break;
2513   case tk_wchar: /* empty parameter list */
2514     break;
2515   case tk_wstring: /* simple parameter list */
2516     u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2517     if (tree) {
2518       proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2519                           *offset-sizeof(u_octet4),4,u_octet4);
2520     }
2521     break;
2522
2523   case tk_fixed: /* simple parameter list */
2524     u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2525     if (tree) {
2526       proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2527                           *offset-sizeof(u_octet2),2,u_octet2);
2528     }
2529
2530     s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2531     if (tree) {
2532       proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2533                           *offset-sizeof(s_octet2),2,s_octet2);
2534     }
2535     break;
2536
2537   case tk_value: /* complex parameter list */
2538     dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2539     break;
2540   case tk_value_box: /* complex parameter list */
2541     dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2542     break;
2543   case tk_native: /* complex parameter list */
2544     dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary);
2545     break;
2546   case tk_abstract_interface: /* complex parameter list */
2547     dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary );
2548     break;
2549   default:
2550     g_warning("giop: Unknown TCKind %u \n", val);
2551     break;
2552   } /* val */
2553
2554   return val;
2555 }
2556
2557
2558
2559 /* Copy a 4 octet sequence from the tvbuff 
2560  * which represents an unsigned long value, and convert
2561  * it to an unsigned long vaule, taking into account byte order.
2562  * offset is first incremented so that it falls on a proper alignment
2563  * boundary for unsigned long values.
2564  * offset is then incremented by 4, to indicate the 4 octets which
2565  * have been processed.
2566  */
2567
2568 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2569
2570   guint32 val;
2571
2572   /* unsigned long values must be aligned on a 4 byte boundary */
2573   while( ( (*offset + boundary) % 4) != 0)
2574           ++(*offset);
2575
2576   val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2577                                  tvb_get_letohl (tvb, *offset);
2578
2579   *offset += 4; 
2580   return val; 
2581 }
2582
2583
2584 /* Copy a 2 octet sequence from the tvbuff 
2585  * which represents an unsigned short value, and convert
2586  * it to an unsigned short value, taking into account byte order.
2587  * offset is first incremented so that it falls on a proper alignment
2588  * boundary for unsigned short values.
2589  * offset is then incremented by 2, to indicate the 2 octets which
2590  * have been processed.
2591  */
2592
2593 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2594
2595   guint16 val;
2596
2597   /* unsigned short values must be aligned on a 2 byte boundary */
2598   while( ( (*offset + boundary) % 2) != 0)
2599           ++(*offset);
2600
2601   val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2602                                  tvb_get_letohs (tvb, *offset);
2603
2604   *offset += 2; 
2605   return val; 
2606 }
2607
2608
2609
2610 /* Copy a wchar from the tvbuff.
2611  * Caller of this function must remember to free the 
2612  * array pointed to by seq.
2613  * This function also increments offset according to
2614  * the wchar size.
2615  *
2616  * For GIOP 1.1 read 2 octets and return size -2. The
2617  * negation means there is no size element in the packet
2618  * and therefore no size to add to the tree.
2619  *
2620  * For GIOP 1.2 read size of wchar and the size
2621  * octets. size is returned as a gint8.
2622  *
2623  * For both GIOP versions the wchar is returned
2624  * as a printable string.
2625  *
2626  */
2627
2628 /* NOTE: This is very primitive in that it just reads
2629  * the wchar as a series of octets and returns them
2630  * to the user. No translation is attempted based on
2631  * byte orientation, nor on code set. I.e it only 
2632  * really reads past the wchar and sets the offset
2633  * correctly.
2634  */
2635
2636 /* The "decoding" is done according to CORBA chapter 15.
2637  * Wchar is not supported for GIOP 1.0.
2638  */
2639
2640 gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2641   
2642   gint slength;
2643   gchar *raw_wstring;
2644
2645   /* CORBA chapter 15:
2646    *   - prior to GIOP 1.2 wchar limited to two octet fixed length.
2647    *   - GIOP 1.2 wchar is encoded as an unsigned binary octet
2648    *     followed by the elements of the octet sequence representing
2649    *     the encoded value of the wchar.
2650    */
2651
2652   *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2653   slength = 2; /* set for GIOP 1.1 length in octets */
2654
2655   if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2656     slength = get_CDR_octet(tvb,offset);
2657
2658   if (slength > 0) {
2659     /* ??? assume alignment is ok for GIOP 1.1 ??? */
2660     get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2661
2662     /* now turn octets (wchar) into something that can be printed by the user */
2663     *seq = make_printable_string(raw_wstring, slength);
2664
2665     g_free(raw_wstring);
2666   }
2667
2668   /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2669   if (header->GIOP_version.minor < 2)
2670     slength = -slength;
2671
2672   return slength;               /* return length */
2673
2674 }
2675
2676
2677 /* Copy a wstring from the tvbuff.
2678  * Caller of this function must remember to free the 
2679  * array pointed to by seq.
2680  * This function also increments offset, according to
2681  * wstring length. length is returned as guint32
2682  */
2683
2684 /* NOTE: This is very primitive in that it just reads
2685  * the wstring as a series of octets and returns them
2686  * to the user. No translation is attempted based on
2687  * byte orientation, nor on code set. I.e it only 
2688  * really reads past the wstring and sets the offset
2689  * correctly.
2690  */
2691
2692 /* The "decoding" is done according to CORBA chapter 15.
2693  * Wstring is not supported for GIOP 1.0.
2694  */
2695
2696
2697 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian, 
2698                        int boundary, MessageHeader * header) {
2699   
2700   guint32 slength;
2701   gchar *raw_wstring;
2702
2703   /* CORBA chapter 15:
2704    *   - prior to GIOP 1.2 wstring limited to two octet fixed length.
2705    *     length and string are NUL terminated (length???).
2706    *   - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2707    *     terminated.
2708    */
2709
2710   *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2711
2712   /* get length, same for all GIOP versions,
2713    * although for 1.2 CORBA doesnt say, so assume. 
2714    */
2715   slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2716
2717 #ifdef DEBUG
2718   if (slength>200) {
2719         fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2720         slength = 5;            /* better than core dumping during debug */
2721   }
2722 #endif
2723   
2724   if (header->GIOP_version.minor < 2) {
2725 #if 0
2726     (*offset)++;  /* must step past \0 delimiter */
2727 #endif
2728     /* assume length is number of characters and not octets, spec not clear */
2729     slength = slength * 2; /* length in octets is 2 * wstring length */
2730   }
2731
2732   if (slength > 0) {
2733     get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2734
2735     /* now turn octets (wstring) into something that can be printed by the user */
2736     *seq = make_printable_string(raw_wstring, slength);
2737
2738     g_free(raw_wstring);
2739   }
2740
2741   return slength;               /* return length */
2742
2743 }
2744
2745
2746
2747 /**
2748  *  Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2749  *  GIOP 1.2
2750  *  typedef short AddressingDisposition;
2751  *  const short KeyAddr = 0;
2752  *  const short ProfileAddr = 1;
2753  *  const short ReferenceAddr = 2;
2754  *  struct IORAddressingInfo {
2755  *    unsigned long selected_profile_index;
2756  *    IOP::IOR ior;
2757  *  };
2758  *
2759  *  union TargetAddress switch (AddressingDisposition) {
2760  *      case KeyAddr: sequence <octet> object_key;
2761  *      case ProfileAddr: IOP::TaggedProfile profile;
2762  *      case ReferenceAddr: IORAddressingInfo ior;
2763  *  };
2764  */
2765
2766 static void
2767 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree, 
2768                        gboolean stream_is_big_endian)
2769 {
2770    guint16 discriminant;
2771    gchar *object_key;
2772    gchar *p_object_key;
2773    guint32 len = 0;
2774    guint32 u_octet4;
2775
2776    discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2777    if(tree)
2778    {
2779      proto_tree_add_text (tree, tvb, *offset -2, 2,
2780                  "TargetAddress Discriminant: %u", discriminant);
2781    }
2782   
2783    switch (discriminant)
2784    {
2785            case 0:  /* KeyAddr */
2786                    len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2787                    if(tree)
2788                    {
2789                       proto_tree_add_text (tree, tvb, *offset -4, 4,
2790                                            "KeyAddr (object key length): %u", len);
2791                    }
2792
2793                    if (len > 0) {
2794
2795                      get_CDR_octet_seq(tvb, &object_key, offset, len);
2796                      p_object_key = make_printable_string( object_key, len );
2797                    
2798                      if(tree)
2799                        {
2800                          proto_tree_add_text (tree, tvb, *offset -len, len,
2801                                                "KeyAddr (object key): %s", p_object_key);
2802                        }
2803                      g_free( p_object_key );
2804                      g_free( object_key );
2805                    }
2806                    break;
2807            case 1: /* ProfileAddr */
2808                    decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2809                                         stream_is_big_endian, NULL);
2810                    break;
2811            case 2: /* ReferenceAddr */
2812                    u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2813
2814                    if(tree)
2815                    {
2816                       proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2817                                            "ReferenceAddr (selected_profile_index): %u", u_octet4);
2818                    }
2819
2820                    decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2821                    break;
2822            default:
2823                    break;
2824    }
2825 }
2826
2827 static void
2828 dissect_reply_body (tvbuff_t *tvb, u_int offset, packet_info *pinfo,
2829                     proto_tree *tree, gboolean stream_is_big_endian,
2830                     guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2831
2832   u_int sequence_length;
2833   gboolean exres = FALSE;               /* result of trying explicit dissectors */
2834   gchar * repoid = NULL;        /* Repositor ID looked up from  objkey */
2835   
2836   /*
2837    * comp_req_list stuff
2838    */
2839
2840   comp_req_list_entry_t * entry = NULL; /* data element in our list */
2841   
2842   guint32 mfn;
2843
2844   switch (reply_status)
2845     {
2846     case SYSTEM_EXCEPTION:
2847
2848       decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2849       break;
2850
2851     case USER_EXCEPTION:
2852
2853       sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2854
2855       if (tree)
2856       {
2857           proto_tree_add_text(tree, tvb, offset-4, 4,
2858                            "Exception length: %u", sequence_length);
2859       }
2860       if (sequence_length != 0)
2861         {
2862           if (tree)
2863           {
2864               proto_tree_add_text(tree, tvb, offset, sequence_length,
2865                            "Exception id: %s",
2866                            tvb_format_text(tvb, offset, sequence_length));
2867           }
2868 #if 1
2869
2870           header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2871
2872           /* read exception id from buffer and store in*/
2873
2874           tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2875           
2876
2877 #endif          
2878           
2879
2880           offset += sequence_length;
2881         }
2882
2883
2884
2885       /*
2886        * Now just fall through to the NO_EXCEPTION part
2887        * as this is common .
2888        */
2889       
2890
2891
2892     case NO_EXCEPTION:
2893
2894
2895       /* lookup MFN in hash directly */
2896  
2897       mfn = get_mfn_from_fn(pinfo->fd->num); 
2898       
2899       if (mfn == pinfo->fd->num)
2900         return;                 /* no matching frame number, what am I */
2901
2902       /* get entry for this MFN */
2903       entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2904
2905       if (!entry)
2906         return;                 /* no matching entry */
2907         
2908
2909       /*
2910        * If this packet is a REPLY to a RESOLVE(request) 
2911        * then decode IOR.
2912        * TODO - make this lookup faster -- FS
2913        */
2914       
2915       if (!strcmp(giop_op_resolve,entry->operation)) {
2916         decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2917         return;         /* done */
2918       }
2919       
2920       /* TODO -- Put stuff here for other "interesting operations" */
2921
2922       /*
2923        *
2924        * Call sub dissector.
2925        * First try an find a explicit sub_dissector, then if that
2926        * fails, try the heuristic method.
2927        */
2928
2929
2930       if(entry->repoid) {    
2931         exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
2932       }
2933
2934       /* Only call heuristic if no explicit dixxector was found */
2935
2936       if(! exres) {
2937         try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
2938       } 
2939
2940
2941       break;
2942       
2943     case LOCATION_FORWARD:
2944       decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2945
2946       break;
2947
2948     case LOCATION_FORWARD_PERM:
2949       decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2950
2951       break;
2952
2953     case NEEDS_ADDRESSING_MODE: {
2954       guint16 addr_disp;
2955       addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2956       if(tree) {
2957         proto_tree_add_text (tree, tvb, offset -2, 2,
2958                              "AddressingDisposition: %u", addr_disp);
2959       }
2960
2961       break;
2962     }
2963
2964     default:
2965       
2966       g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
2967       
2968       break;
2969       
2970     } /* switch */
2971   
2972   g_free(repoid);               /* free resource */
2973   
2974   return;                       /* done */
2975   
2976 }
2977
2978
2979
2980
2981
2982 /* The format of the Reply Header for GIOP 1.0 and 1.1
2983  * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
2984
2985     struct ReplyHeader_1_0 {
2986           IOP::ServiceContextList service_context;
2987           unsigned long request_id;
2988           ReplyStatusType_1_0 reply_status;
2989     };
2990  */
2991
2992 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
2993                                 MessageHeader * header,
2994                                 gboolean stream_is_big_endian) {
2995
2996   guint32 offset = 0;
2997   guint32 request_id;
2998   guint32 reply_status;
2999   proto_tree *reply_tree = NULL;
3000   proto_item *tf;
3001   guint32 mfn;                  /* matching frame number */
3002
3003   if (tree) {
3004     tf = proto_tree_add_text (tree, tvb, offset, -1,
3005                               "General Inter-ORB Protocol Reply");
3006     if (reply_tree == NULL)
3007       {
3008         reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3009         
3010       }
3011   }
3012   
3013   /*
3014    * Decode IOP::ServiceContextList
3015    */
3016   
3017   decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3018
3019   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3020
3021   if (check_col(pinfo->cinfo, COL_INFO)) {
3022     col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3023   }
3024
3025   if (tree) {
3026     proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3027                          "Request id: %u", request_id);
3028   }
3029
3030   reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3031
3032   if (check_col(pinfo->cinfo, COL_INFO)) {
3033     col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3034                     val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3035
3036   }
3037
3038   if (tree) {
3039     proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3040                          "Reply status: %s",
3041                          val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3042     
3043   }
3044
3045   /*
3046    * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3047    */
3048
3049   if (! pinfo->fd->flags.visited) {
3050     mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3051     if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3052       insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3053     }
3054   }
3055
3056   header->req_id = request_id;          /* save for sub dissector */
3057   header->rep_status = reply_status;   /* save for sub dissector */
3058
3059   dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3060     reply_status, header,tree);
3061
3062
3063 }
3064
3065 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3066  *  and 1.1 header, only the fields have been rearranged.  From Section
3067  *  15.4.3.1 of the CORBA 2.4 specification:
3068  *
3069  *   struct ReplyHeader_1_2 {
3070  *         unsigned long request_id;
3071  *         ReplyStatusType_1_2 reply_status;
3072  *         IOP:ServiceContextList service_context; 
3073  *    };
3074  */
3075
3076 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3077                                     proto_tree * tree,
3078                                     MessageHeader * header,
3079                                     gboolean stream_is_big_endian) {
3080
3081   u_int offset = 0;
3082   guint32 request_id;
3083   guint32 reply_status;
3084   proto_tree *reply_tree = NULL;
3085   proto_item *tf;
3086   guint32 mfn;                  /* matching frame number */
3087   
3088   if (tree) {
3089     tf = proto_tree_add_text (tree, tvb, offset, -1,
3090                               "General Inter-ORB Protocol Reply");
3091     reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3092   }
3093   
3094   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3095   
3096   if (check_col(pinfo->cinfo, COL_INFO)) {
3097     col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3098   }
3099
3100   if (tree) {
3101     proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3102                          "Request id: %u", request_id);
3103   }
3104
3105   reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3106   
3107   if (check_col(pinfo->cinfo, COL_INFO)) {
3108     col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3109                     val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3110
3111   }
3112
3113   if (tree) {
3114     proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3115                          "Reply status: %s",
3116                          val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3117
3118   }
3119
3120   /*
3121    * Decode IOP::ServiceContextList
3122    */
3123
3124   decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3125
3126   /*
3127    * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3128    */
3129
3130   set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3131
3132   /*
3133    * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3134    */
3135   
3136   if (! pinfo->fd->flags.visited) {
3137     mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3138     if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3139       insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3140     }
3141   }
3142
3143   /*
3144    * Add header to argument list so sub dissector can get header info.
3145    */
3146
3147   header->req_id = request_id;          /* save for sub dissector */
3148   header->rep_status = reply_status;   /* save for sub dissector */
3149
3150   dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3151                      reply_status,header,tree);
3152
3153 }
3154
3155
3156
3157 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3158                         proto_tree * tree,
3159                         gboolean stream_is_big_endian) {
3160
3161   u_int offset = 0;
3162   guint32 request_id;
3163   proto_tree *cancel_request_tree = NULL;
3164   proto_item *tf;
3165
3166   if (tree) {
3167     tf = proto_tree_add_text (tree, tvb, offset, -1,
3168                               "General Inter-ORB Protocol CancelRequest");
3169     cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3170   }
3171
3172   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3173   
3174   if (check_col(pinfo->cinfo, COL_INFO)) {
3175     col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3176   }
3177
3178   if (tree) {
3179     proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4,
3180                          "Request id: %u", request_id);
3181   }
3182
3183   
3184 }
3185
3186 /**  The formats for GIOP 1.0 and 1.1 Request messages are defined
3187  *   in section 15.4.2.1 of the CORBA 2.4 specification.
3188  *
3189  *   struct RequestHeader{
3190  *          IOP::ServiceContextList   service_context;
3191  *          unsigned long             request_id;
3192  *          boolean                   response_expected;
3193  *          octet                     reserved[3];  // Only in GIOP 1.1
3194  *          sequence<octet>           object_key;
3195  *          string                    operation;
3196  *          CORBA::OctetSeq           requesting_principal;
3197  *   }
3198  */
3199 static void
3200 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3201                         proto_tree * tree,
3202                         MessageHeader * header, gboolean stream_is_big_endian)
3203 {
3204   guint32 offset = 0;
3205   guint32 request_id;
3206   guint32 len = 0;
3207
3208   guint32 objkey_len = 0;       /* object key length */
3209   gchar *objkey = NULL;         /* object key sequence */
3210   gchar *print_objkey;          /* printable object key sequence */
3211   gboolean exres = FALSE;       /* result of trying explicit dissectors */
3212
3213   gchar *operation;
3214   gchar *requesting_principal;
3215   gchar *print_requesting_principal;
3216   guint8 response_expected;
3217   gchar *reserved;
3218   proto_tree *request_tree = NULL;
3219   proto_item *tf;
3220
3221   gchar *repoid = NULL;         /* from object key lookup in objkey hash */
3222
3223
3224   if (tree)
3225     {
3226       tf = proto_tree_add_text (tree, tvb, offset, -1,
3227                                 "General Inter-ORB Protocol Request");
3228       if (request_tree == NULL)
3229         {
3230           request_tree = proto_item_add_subtree (tf, ett_giop_request);
3231
3232         }
3233     }
3234
3235
3236
3237
3238   /*
3239    * Decode IOP::ServiceContextList
3240    */
3241   
3242   decode_ServiceContextList(tvb, request_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3243
3244
3245   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3246   if (check_col(pinfo->cinfo, COL_INFO))
3247     {
3248       col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3249     }
3250   if (tree)
3251     {
3252       proto_tree_add_text (request_tree, tvb, offset-4, 4,
3253                            "Request id: %u", request_id);
3254     }
3255
3256   response_expected = tvb_get_guint8( tvb, offset );
3257   offset += 1;
3258   if (check_col(pinfo->cinfo, COL_INFO))
3259     {
3260       col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3261                 response_expected ? "two-way" : "one-way");
3262     }
3263   if (tree)
3264     {
3265       proto_tree_add_text (request_tree, tvb, offset-1, 1,
3266                            "Response expected: %u", response_expected);
3267     }
3268
3269   if( header->GIOP_version.minor > 0)
3270   {
3271      get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3272      if (tree)
3273        {
3274          proto_tree_add_text (request_tree, tvb, offset-3, 3,
3275                            "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3276        }
3277      g_free(reserved);
3278   }
3279
3280
3281
3282   /* Length of object_key sequence */
3283   objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3284
3285
3286   if(tree)
3287   {
3288          proto_tree_add_text (request_tree, tvb, offset-4, 4,
3289          /**/                 "Object Key length: %u", objkey_len);
3290   } 
3291
3292   if (objkey_len > 0)
3293   {
3294        get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3295
3296        print_objkey = make_printable_string(objkey, objkey_len);
3297
3298        if(tree)
3299        {
3300          proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
3301          /**/                 "Object Key: %s", print_objkey);
3302
3303        }
3304
3305        g_free( print_objkey );  
3306   } 
3307
3308   /*
3309    * Register a cleanup function in case on of our tvbuff accesses
3310    * throws an exception. We need to clean up objkey.
3311    */
3312   CLEANUP_PUSH(g_free, objkey);
3313
3314   /* length of operation string and string */ 
3315   len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3316   if(tree)
3317   {
3318          proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3319          /**/                 "Operation length: %u", len);
3320   } 
3321
3322   if( len > 0)
3323   {
3324        if (check_col(pinfo->cinfo, COL_INFO))
3325        {
3326          col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3327        }
3328        if(tree)
3329        {
3330          proto_tree_add_text (request_tree, tvb, offset - len, len,
3331          /**/                 "Operation: %s", operation);
3332
3333        }
3334   }
3335
3336   /*
3337    * Register a cleanup function in case on of our tvbuff accesses
3338    * throws an exception. We need to clean up operation.
3339    */
3340   CLEANUP_PUSH(g_free, operation);
3341
3342   /* length of requesting_principal string */ 
3343   len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3344   if(tree)
3345   {
3346          proto_tree_add_text (request_tree, tvb, offset-4, 4,
3347          /**/                 "Requesting Principal Length: %u", len);
3348   } 
3349
3350   if( len > 0)
3351   {
3352        get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3353
3354        print_requesting_principal = make_printable_string(requesting_principal, len);
3355
3356        if(tree)
3357        {
3358          proto_tree_add_text (request_tree, tvb, offset - len, len, 
3359          /**/                 "Requesting Principal: %s", print_requesting_principal);
3360
3361        }
3362
3363        g_free( print_requesting_principal );
3364        g_free( requesting_principal );
3365   }
3366
3367
3368   /*
3369    * Save FN,reqid,and operation for later. Add sub_handle later.
3370    * But only if user is NOT clicking.
3371    */
3372
3373   if (! pinfo->fd->flags.visited)
3374     giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3375                                                          request_id,operation,NULL);
3376
3377   
3378   /*
3379    * Call subdissector here before freeing "operation" and "key"
3380    * pass request_id also. 
3381    * First try an find an explicit sub_dissector, then if that
3382    * fails, try the heuristic method.
3383    *
3384    */
3385
3386
3387   header->req_id = request_id;          /* save for sub dissector */
3388   repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3389
3390
3391   if(repoid) {    
3392     exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3393   }
3394
3395   /* Only call heuristic if no explicit dissector was found */
3396
3397   if (! exres) {
3398     try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3399   }
3400   
3401
3402   /*
3403    * We're done with operation, so we can call the cleanup handler to free
3404    * it, and then pop the cleanup handler.
3405    */
3406   CLEANUP_CALL_AND_POP;
3407
3408   /*
3409    * We're done with objkey, so we can call the cleanup handler to free
3410    * it, and then pop the cleanup handler.
3411    */
3412   CLEANUP_CALL_AND_POP;
3413
3414 }
3415
3416 /**  The format of a GIOP 1.2 RequestHeader message is 
3417  *   (CORBA 2.4, sec. 15.4.2):
3418  *
3419  *   struct RequestHeader_1_2 {
3420  *       unsigned long request_id;
3421  *       octet response_flags;
3422  *       octet reserved[3];
3423  *       TargetAddress target;
3424  *       string operation;
3425  *       IOP::ServiceContextList service_context;
3426  *       // requesting_principal not in GIOP 1.2
3427  *   };
3428  */
3429 static void
3430 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3431                         proto_tree * tree,
3432                         MessageHeader * header, gboolean stream_is_big_endian)
3433 {
3434   guint32 offset = 0;
3435   guint32 request_id;
3436   guint32 len = 0;
3437   guint8 response_flags;
3438   gchar *reserved;
3439   gchar *operation = NULL;
3440   proto_tree *request_tree = NULL;
3441   proto_item *tf;
3442   gboolean exres = FALSE;               /* result of trying explicit dissectors */
3443
3444   gchar *repoid = NULL;
3445
3446
3447   if (tree)
3448     {
3449       tf = proto_tree_add_text (tree, tvb, offset, -1,
3450                                 "General Inter-ORB Protocol Request");
3451       request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3452     }
3453
3454   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3455   if (check_col(pinfo->cinfo, COL_INFO))
3456     {
3457       col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3458     }
3459   if (request_tree)
3460     {
3461       proto_tree_add_text (request_tree, tvb, offset-4, 4,
3462                            "Request id: %u", request_id);
3463     }
3464
3465   response_flags = tvb_get_guint8( tvb, offset );
3466   offset += 1;
3467   if (request_tree)
3468     {
3469       proto_tree_add_text (request_tree, tvb, offset-1, 1,
3470                            "Response flags: %s (%u)",
3471                                 match_strval(response_flags, sync_scope),  
3472                                 response_flags);
3473     }
3474
3475   get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3476   if (request_tree)
3477    {
3478      proto_tree_add_text (request_tree, tvb, offset-3, 3,
3479            "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3480    }
3481   g_free(reserved);
3482
3483   dissect_target_address(tvb, pinfo, &offset, request_tree, stream_is_big_endian);
3484
3485   /* length of operation string */ 
3486   len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3487   if(tree)
3488   {
3489          proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3490          /**/                 "Operation length: %u", len);
3491   } 
3492
3493   if( len > 0)
3494   {
3495        if (check_col(pinfo->cinfo, COL_INFO))
3496        {
3497          col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3498        }
3499        if(request_tree)
3500        {
3501          proto_tree_add_text (request_tree, tvb, offset - len, len,
3502          /**/                 "Operation: %s", operation);
3503
3504        }
3505
3506   }
3507
3508   /*
3509    * Register a cleanup function in case on of our tvbuff accesses
3510    * throws an exception. We need to clean up operation.
3511    */
3512   CLEANUP_PUSH(g_free, operation);
3513
3514   /*
3515    * Decode IOP::ServiceContextList
3516    */
3517
3518   decode_ServiceContextList(tvb, request_tree, &offset,  stream_is_big_endian, GIOP_HEADER_SIZE);
3519
3520   /*
3521    * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3522    * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3523    * GIOP octet stream start.
3524    */
3525
3526   set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3527
3528   /*
3529    * Save FN,reqid,and operation for later. Add sub_handle later.
3530    * But only if user is NOT clicking.
3531    */
3532   
3533   if (! pinfo->fd->flags.visited)
3534     giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3535                                                          request_id,operation,NULL);
3536
3537   /*
3538    *
3539    * Call sub dissector.
3540    * First try an find a explicit sub_dissector, then if that
3541    * fails, try the heuristic method.
3542    */
3543   
3544
3545   if(repoid) {    
3546     exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3547   }
3548
3549   /* Only call heuristic if no explicit dissector was found */
3550
3551   if (! exres) {
3552     try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3553   }
3554   
3555
3556   /*
3557    * We're done with operation, so we can call the cleanup handler to free
3558    * it, and then pop the cleanup handler.
3559    */
3560   CLEANUP_CALL_AND_POP;
3561 }
3562
3563 static void
3564 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
3565                         proto_tree * tree, MessageHeader * header,
3566                         gboolean stream_is_big_endian)
3567 {
3568   guint32 offset = 0;
3569   guint32 request_id;
3570   guint32 len = 0;
3571   gchar *object_key;
3572   gchar *p_object_key;
3573   proto_tree *locate_request_tree = NULL;
3574   proto_item *tf;
3575
3576   if (tree)
3577     {
3578       tf = proto_tree_add_text (tree, tvb, offset, -1,
3579                                 "General Inter-ORB Locate Request");
3580       if (locate_request_tree == NULL)
3581         {
3582           locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3583
3584         }
3585     }
3586
3587   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3588   if (check_col(pinfo->cinfo, COL_INFO))
3589     {
3590       col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3591     }
3592   if (locate_request_tree)
3593     {
3594       proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3595                            "Request id: %u", request_id);
3596     }
3597
3598   if(header->GIOP_version.minor < 2)
3599   {
3600         len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3601         if (locate_request_tree)
3602           {
3603             proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3604                                  "Object Key length: %u", len);
3605           }
3606
3607         if (len > 0) {
3608           get_CDR_octet_seq(tvb, &object_key, &offset, len);
3609
3610           p_object_key = make_printable_string(object_key, len);
3611   
3612           if(locate_request_tree)
3613             {
3614
3615               proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
3616                                    "Object Key: %s", p_object_key);
3617             }
3618
3619           g_free(p_object_key);
3620           g_free(object_key);
3621         }
3622   }
3623   else     /* GIOP 1.2 and higher */
3624   {
3625       dissect_target_address(tvb, pinfo, &offset, locate_request_tree, 
3626                              stream_is_big_endian);
3627
3628   }
3629 }
3630
3631 static void
3632 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3633                         proto_tree * tree, MessageHeader * header,
3634                         gboolean stream_is_big_endian)
3635 {
3636   guint32 offset = 0;
3637   guint32 request_id;
3638   guint32 locate_status;
3639   guint16 addr_disp;
3640
3641   proto_tree *locate_reply_tree = NULL;
3642   proto_item *tf;
3643
3644   if (tree)
3645     {
3646       tf = proto_tree_add_text (tree, tvb, offset, -1,
3647                                 "General Inter-ORB Locate Reply");
3648       if (locate_reply_tree == NULL)
3649         {
3650           locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3651
3652         }
3653     }
3654
3655   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3656   if (check_col(pinfo->cinfo, COL_INFO))
3657     {
3658       col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3659     }
3660   if (locate_reply_tree)
3661     {
3662       proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3663                            "Request id: %u", request_id);
3664     }
3665
3666   locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3667   if (locate_reply_tree)
3668     {
3669       proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3670                            "Locate status: %s", 
3671                            match_strval(locate_status, giop_locate_status_types)
3672                            );
3673     }
3674
3675   /* Decode the LocateReply body.
3676    *
3677    * For GIOP 1.0 and 1.1 body immediately follows header.
3678    * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3679    * spin up.
3680    */
3681
3682   if (header->GIOP_version.minor > 1) {
3683     while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3684       ++(offset);
3685   }
3686
3687   switch(locate_status) {
3688   case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3689   case OBJECT_FORWARD_PERM:
3690     decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3691     break;
3692   case LOC_SYSTEM_EXCEPTION:
3693     decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3694     break;
3695   case LOC_NEEDS_ADDRESSING_MODE:
3696     addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3697     if(locate_reply_tree) {
3698       proto_tree_add_text (tree, tvb, offset -2, 2,
3699                            "AddressingDisposition: %u", addr_disp);
3700     }
3701     break;
3702   default: /* others have no reply body */
3703     break;
3704   }
3705
3706 }
3707
3708 static void
3709 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3710                         gboolean stream_is_big_endian)
3711 {
3712   guint32 offset = 0;
3713   guint32 request_id;
3714   proto_tree *fragment_tree = NULL;
3715   proto_item *tf;
3716
3717   if (tree)
3718     {
3719       tf = proto_tree_add_text (tree, tvb, offset, -1,
3720                                 "General Inter-ORB Fragment");
3721       if (fragment_tree == NULL)
3722         {
3723           fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3724
3725         }
3726     }
3727
3728   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3729   if (check_col(pinfo->cinfo, COL_INFO))
3730     {
3731       col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3732     }
3733   if (fragment_tree )
3734     {
3735       proto_tree_add_text (fragment_tree, tvb, offset-4, 4,
3736                            "Request id: %u", request_id);
3737     }
3738                                    
3739 }
3740
3741
3742 /* Main entry point */
3743
3744 gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3745   u_int offset = 0;
3746   MessageHeader header;
3747   tvbuff_t *giop_header_tvb;
3748   tvbuff_t *payload_tvb;
3749
3750   proto_tree *clnp_tree = NULL;
3751   proto_item *ti;
3752   u_int message_size;
3753   u_int minor_version;
3754   gboolean stream_is_big_endian;
3755
3756
3757   /* DEBUG */
3758   
3759 #if DEBUG
3760   giop_dump_collection(cd_module_hash);
3761   giop_dump_collection(cd_objkey_hash);
3762   giop_dump_collection(cd_heuristic_users);
3763   giop_dump_collection(cd_complete_reply_hash);
3764   giop_dump_collection(cd_complete_request_list);
3765 #endif
3766
3767   header.exception_id = NULL;
3768
3769   /* check magic number and version */
3770
3771
3772   /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
3773
3774   if (tvb_length_remaining(tvb, 0) < GIOP_HEADER_SIZE)
3775     {
3776       /* Not enough data captured to hold the GIOP header; don't try
3777          to interpret it as GIOP. */
3778       return FALSE;
3779     }
3780
3781   giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3782   payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3783   
3784   /*
3785    * because I have added extra elements in MessageHeader struct
3786    * for sub dissectors. -- FS
3787    */
3788
3789   tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3790
3791   if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
3792     {
3793       /* Not a GIOP message. */
3794
3795       return FALSE;
3796     }
3797
3798   if (check_col (pinfo->cinfo, COL_PROTOCOL))
3799     {
3800       col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3801     }
3802
3803   if (header.GIOP_version.major != GIOP_MAJOR ||
3804       ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3805     {
3806       /* Bad version number; should we note that and dissect the rest
3807          as data, or should we return FALSE on the theory that it
3808          might have been some other packet that happened to begin with
3809          "GIOP"?  We shouldn't do *both*, so we return TRUE, for now.
3810          If we should return FALSE, we should do so *without* setting
3811          the "Info" column, *without* setting the "Protocol" column,
3812          and *without* adding anything to the protocol tree. */
3813
3814       if (check_col (pinfo->cinfo, COL_INFO))
3815         {
3816           col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3817                         header.GIOP_version.major, header.GIOP_version.minor);
3818         }
3819       if (tree)
3820         {
3821           ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
3822           clnp_tree = proto_item_add_subtree (ti, ett_giop);
3823           proto_tree_add_text (clnp_tree, giop_header_tvb, 0, -1,
3824                                "Version %u.%u not supported",
3825                                header.GIOP_version.major,
3826                                header.GIOP_version.minor);
3827         }
3828       call_dissector(data_handle,payload_tvb, pinfo, tree);
3829       return TRUE;
3830     }
3831
3832   if (check_col (pinfo->cinfo, COL_INFO)) 
3833   { 
3834       col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3835                     header.GIOP_version.major, header.GIOP_version.minor,
3836                     val_to_str(header.message_type, giop_message_types,
3837                                "Unknown message type (0x%02x)"));
3838   }
3839
3840   stream_is_big_endian = is_big_endian (&header);
3841
3842   if (stream_is_big_endian)
3843     message_size = pntohl (&header.message_size);
3844   else
3845     message_size = pletohl (&header.message_size);
3846
3847   if (tree)
3848     {
3849       ti = proto_tree_add_item (tree, proto_giop, tvb, 0, 12, FALSE);
3850       clnp_tree = proto_item_add_subtree (ti, ett_giop);
3851       proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3852                            "Magic number: %s", GIOP_MAGIC);
3853       proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3854                            "Version: %u.%u",
3855                            header.GIOP_version.major,
3856                            header.GIOP_version.minor);
3857       switch (minor_version)
3858         {
3859         case 2:
3860         case 1:
3861           proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3862                                "Flags: 0x%02x (%s %s)",
3863                                header.flags,
3864                                (stream_is_big_endian) ? "big-endian" : "little-endian",
3865                                (header.flags & 0x02) ? " fragment" : "");
3866           break;
3867         case 0:
3868           proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3869                                "Byte ordering: %s-endian",
3870                                (stream_is_big_endian) ? "big" : "little");
3871           break;
3872         default:
3873           break;
3874         }                       /* minor_version */
3875
3876       proto_tree_add_uint_format (clnp_tree,
3877                                   hf_giop_message_type,
3878                                   giop_header_tvb, 7, 1,
3879                                   header.message_type,
3880                                   "Message type: %s", match_strval(header.message_type, giop_message_types));
3881
3882       proto_tree_add_uint (clnp_tree,
3883                            hf_giop_message_size,
3884                            giop_header_tvb, 8, 4, message_size);
3885
3886     }                           /* tree */
3887
3888 #if 0
3889   if (check_col (pinfo->cinfo, COL_INFO)) 
3890   { 
3891       col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3892                     header.GIOP_version.major, header.GIOP_version.minor,
3893                     match_strval(header.message_type, giop_message_types));
3894   }
3895 #endif
3896
3897   switch (header.message_type)
3898     {
3899
3900     case Request:
3901       if(header.GIOP_version.minor < 2)
3902       {
3903            dissect_giop_request_1_1 (payload_tvb, pinfo, tree,
3904                                      &header, stream_is_big_endian);
3905       }
3906       else
3907       {    
3908            dissect_giop_request_1_2 (payload_tvb, pinfo, tree,
3909                                      &header, stream_is_big_endian);
3910       }
3911       
3912       break;
3913
3914
3915     case Reply:
3916       if(header.GIOP_version.minor < 2)
3917         {
3918            dissect_giop_reply (payload_tvb, pinfo, tree, &header,
3919                                stream_is_big_endian);
3920         }
3921       else
3922         {
3923            dissect_giop_reply_1_2 (payload_tvb, pinfo, tree,
3924                                    &header, stream_is_big_endian);
3925         }
3926       break;
3927     case CancelRequest:
3928         dissect_giop_cancel_request(payload_tvb, pinfo, tree,
3929                                     stream_is_big_endian);
3930         break;
3931     case LocateRequest:
3932         dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
3933                                     stream_is_big_endian);
3934         break;
3935     case LocateReply:
3936         dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
3937                                   stream_is_big_endian);
3938         break;
3939     case Fragment:
3940         dissect_giop_fragment(payload_tvb, pinfo, tree,
3941                               stream_is_big_endian);
3942         break;  
3943     default:
3944       break;
3945
3946     }                           /* switch message_type */
3947
3948
3949   /*
3950    * XXX - we should catch exceptions here, so that we can free
3951    * this if an exception is thrown.
3952    * We'd then have to forward the exception.
3953    */
3954   if (header.exception_id != NULL)
3955     g_free(header.exception_id);
3956
3957   return TRUE;
3958 }
3959
3960 void
3961 proto_register_giop (void)
3962 {
3963   static hf_register_info hf[] = {
3964     { &hf_giop_message_type,
3965      { "Message type", "giop.type",
3966        FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
3967     },
3968     
3969     { &hf_giop_message_size,
3970       { "Message size", "giop.len",
3971         FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3972     },
3973
3974     { &hf_giop_repoid,
3975      { "Repository ID", "giop.repoid",
3976        FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
3977     },
3978
3979     { &hf_giop_string_length,
3980      { "String Length", "giop.strlen",
3981        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3982     },
3983
3984     { &hf_giop_sequence_length,
3985      { "Sequence Length", "giop.seqlen",
3986        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
3987     },
3988
3989     { &hf_giop_profile_id,
3990      { "Profile ID", "giop.profid",
3991        FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
3992     },
3993
3994
3995     { &hf_giop_type_id,
3996      { "IOR::type_id", "giop.typeid",
3997        FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
3998     },
3999
4000     { &hf_giop_iiop_v_maj,
4001      { "IIOP Major Version", "giop.iiop_vmaj",
4002        FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4003     }
4004     ,
4005     { &hf_giop_iiop_v_min,
4006      { "IIOP Minor Version", "giop.iiop_vmin",
4007        FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4008     },
4009
4010     { &hf_giop_endianess,
4011      { "Endianess", "giop.endianess",
4012        FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4013     },
4014
4015     { &hf_giop_IIOP_tag,
4016      { "IIOP Component TAG", "giop.iioptag",
4017        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4018     },
4019
4020     { &hf_giop_IOR_tag,
4021      { "IOR Profile TAG", "giop.iortag",
4022        FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4023     },
4024
4025     { &hf_giop_TCKind,
4026      { "TypeCode enum", "giop.TCKind",
4027        FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4028     },
4029
4030     { &hf_giop_typecode_count,
4031      { "TypeCode count", "giop.tccount",
4032        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4033     },
4034
4035     { &hf_giop_typecode_default_used,
4036      { "default_used", "giop.tcdefault_used",
4037        FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4038     },
4039
4040     { &hf_giop_typecode_digits,
4041      { "Digits", "giop.tcdigits",
4042        FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4043     },
4044
4045
4046     { &hf_giop_typecode_length,
4047      { "Length", "giop.tclength",
4048        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4049     },
4050
4051     { &hf_giop_typecode_max_length,
4052      { "Maximum length", "giop.tcmaxlen",
4053        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4054     },
4055
4056     { &hf_giop_typecode_member_name,
4057      { "TypeCode member name", "giop.tcmemname",
4058        FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4059     },
4060
4061     { &hf_giop_typecode_name,
4062      { "TypeCode name", "giop.tcname",
4063        FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4064     },
4065
4066     { &hf_giop_typecode_scale,
4067      { "Scale", "giop.tcscale",
4068        FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4069     },
4070
4071     { &hf_giop_typecode_ValueModifier,
4072      { "ValueModifier", "giop.tcValueModifier",
4073        FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4074     },
4075
4076     { &hf_giop_typecode_Visibility,
4077      { "Visibility", "giop.tcVisibility",
4078        FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4079     },
4080
4081
4082
4083     { &hf_giop_type_boolean,
4084       { "TypeCode boolean data", "giop.tcboolean",
4085         FT_BOOLEAN, BASE_DEC,  NULL, 0x0, "", HFILL }
4086     },
4087
4088     { &hf_giop_type_char,
4089       { "TypeCode char data", "giop.tcchar",
4090         FT_UINT8, BASE_DEC,  NULL, 0x0, "", HFILL }
4091     },
4092
4093     { &hf_giop_type_double,
4094       { "TypeCode double data", "giop.tcdouble",
4095         FT_DOUBLE, BASE_DEC,  NULL, 0x0, "", HFILL }
4096     },
4097
4098     { &hf_giop_type_enum,
4099      { "TypeCode enum data", "giop.tcenumdata",
4100        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4101     },
4102
4103     /*
4104      * float as double ?? -- FIX
4105      */
4106
4107     { &hf_giop_type_float,
4108       { "TypeCode float data", "giop.tcfloat",
4109         FT_DOUBLE, BASE_DEC,  NULL, 0x0, "", HFILL }
4110     },
4111
4112     { &hf_giop_type_long,
4113      { "TypeCode long data", "giop.tclongdata",
4114        FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4115     },
4116
4117     { &hf_giop_type_octet,
4118       { "TypeCode octet data", "giop.tcoctet",
4119         FT_UINT8, BASE_DEC,  NULL, 0x0, "", HFILL }
4120     },
4121
4122     { &hf_giop_type_short,
4123      { "TypeCode short data", "giop.tcshortdata",
4124        FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4125     },
4126
4127     { &hf_giop_type_string,
4128       { "TypeCode string data", "giop.tcstring",
4129         FT_STRING, BASE_DEC,  NULL, 0x0, "", HFILL }
4130     },
4131
4132     { &hf_giop_type_ulong,
4133      { "TypeCode ulong data", "giop.tculongdata",
4134        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4135     },
4136
4137     { &hf_giop_type_ushort,
4138      { "TypeCode ushort data", "giop.tcushortdata",
4139        FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4140     },
4141
4142     /*
4143      * IIOP Module - Chapter 15.10.2
4144      */
4145
4146     { &hf_giop_iiop_host,
4147      { "IIOP::Profile_host", "giop.iiop.host",
4148        FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4149     }
4150     ,
4151
4152     { &hf_giop_iiop_port,
4153      { "IIOP::Profile_port", "giop.iiop.port",
4154        FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4155     }
4156     ,
4157
4158     /*
4159      * IIOP ServiceContext
4160      */
4161
4162     { &hf_giop_iop_vscid,
4163      { "VSCID", "giop.iiop.vscid",
4164        FT_UINT32, BASE_HEX, NULL, 0xfffff000, "", HFILL }
4165     }
4166     ,
4167
4168     { &hf_giop_iop_scid,
4169      { "SCID", "giop.iiop.scid",
4170        FT_UINT32, BASE_HEX, NULL, 0x00000fff, "", HFILL }
4171     }
4172     ,
4173
4174
4175   };
4176
4177   static gint *ett[] = {
4178     &ett_giop,
4179     &ett_giop_reply,
4180     &ett_giop_request,
4181     &ett_giop_cancel_request,
4182     &ett_giop_locate_request,
4183     &ett_giop_locate_reply,
4184     &ett_giop_fragment,
4185     &ett_giop_scl,
4186     &ett_giop_ior
4187
4188   };
4189   proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4190                                        "giop");
4191   proto_register_field_array (proto_giop, hf, array_length (hf));
4192   proto_register_subtree_array (ett, array_length (ett));
4193
4194
4195   /* register init routine */
4196
4197   register_init_routine( &giop_init); /* any init stuff */
4198
4199   /*
4200    * Init the giop user module hash tables here, as giop users
4201    * will populate it via register_giop_user_module BEFORE my
4202    * own giop_init() is called.
4203    */
4204
4205   giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4206   
4207   giop_module_keys = g_mem_chunk_new("giop_module_keys",
4208                                      sizeof(struct giop_module_key),
4209                                      giop_module_init_count * sizeof(struct giop_module_key), 
4210                                      G_ALLOC_AND_FREE);
4211   
4212   giop_module_vals = g_mem_chunk_new("giop_module_vals", 
4213                                      sizeof(struct giop_module_val),
4214                                      giop_module_init_count * sizeof(struct giop_module_val), 
4215                                      G_ALLOC_AND_FREE);
4216   
4217 }
4218
4219
4220
4221 void proto_reg_handoff_giop (void) {
4222   data_handle = find_dissector("data");
4223   heur_dissector_add("tcp", dissect_giop, proto_giop);
4224   /* Support DIOP (GIOP/UDP) */
4225   heur_dissector_add("udp", dissect_giop, proto_giop);
4226 }
4227
4228
4229
4230
4231 /*
4232  * Decode IOR
4233  *
4234  * Ref Corba v2.4.2 Chapter 13
4235  *
4236  */
4237
4238 /*
4239
4240 module IOP{ 
4241
4242     typedef unsigned long ProfileId;
4243
4244     const ProfileId TAG_INTERNET_IOP = 0;
4245     const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4246
4247     struct TaggedProfile {
4248       ProfileId tag;
4249       sequence <octet> profile_data;
4250     };
4251
4252     struct IOR {
4253       string type_id;
4254       sequence <TaggedProfile> profiles;
4255     };
4256
4257     typedef unsigned long ComponentId;
4258
4259     struct TaggedComponent {
4260       ComponentId tag;
4261       sequence <octet> component_data;
4262     };
4263
4264     typedef sequence <TaggedComponent> MultipleComponentProfile;
4265
4266 };
4267
4268 */
4269
4270 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4271                 guint32 boundary, gboolean stream_is_big_endian) {
4272
4273
4274   guint32 seqlen_p;             /* sequence length of profiles */
4275   guint32 u_octet4;
4276
4277   proto_tree *tree = NULL;      /* IOR tree */
4278   proto_item *tf;
4279
4280   gchar *repobuf;               /* for repository ID */
4281
4282   guint32 i;
4283
4284   /* create a subtree */
4285
4286   if (ptree) {
4287     tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
4288     tree = proto_item_add_subtree (tf, ett_giop_ior);
4289   }
4290
4291
4292   /* Get type_id  == Repository ID */
4293
4294   u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4295
4296   if (tree) {    
4297     proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4298                         *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4299     if (u_octet4 > 0) {
4300       proto_tree_add_string(tree,hf_giop_type_id,tvb,
4301                             *offset-u_octet4,u_octet4,repobuf);
4302     }
4303   }
4304
4305   /*
4306    * Register a cleanup function in case on of our tvbuff accesses
4307    * throws an exception. We need to clean up repobuf.
4308    * We can't free it yet, as we must wait until we have the object
4309    * key, as we have to add both to the hash table.
4310    */
4311   CLEANUP_PUSH(g_free, repobuf);
4312
4313   /* Now get a sequence of profiles */
4314   /* Get sequence length (number of elements) */
4315   
4316   seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4317   if (tree) {
4318     proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4319                         *offset-sizeof(seqlen_p),4,seqlen_p);
4320   }
4321   
4322
4323   /* fetch all TaggedProfiles in this sequence */
4324   
4325   for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4326     decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4327   }
4328
4329   /*
4330    * We're done with repobuf, so we can call the cleanup handler to free
4331    * it, and then pop the cleanup handler.
4332    */
4333   CLEANUP_CALL_AND_POP;
4334
4335 }
4336
4337 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4338                                  guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4339
4340   guint32 seqlen_pd;            /* sequence length of profile data */
4341
4342   guint32 pidtag;               /* profile ID TAG */
4343
4344   gchar *profile_data;          /* profile_data pointer */
4345   gchar *p_profile_data;        /* printable profile_data pointer */
4346
4347   guint32 new_boundary;         /* for encapsulations encountered */
4348   gboolean new_big_endianess;   /* for encapsulations encountered */
4349
4350   /* Get ProfileId tag */
4351
4352   pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4353
4354   if (tree) {
4355     proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4356                         *offset-sizeof(pidtag),4,pidtag);
4357   }
4358
4359   /* get sequence length, new endianness and boundary for encapsulation */
4360   
4361   seqlen_pd = get_CDR_encap_info(tvb, tree, offset, 
4362                                  stream_is_big_endian, boundary,
4363                                  &new_big_endianess, &new_boundary);
4364
4365   /* return if zero length sequence */
4366
4367   if(seqlen_pd == 0)
4368     return;
4369
4370     
4371   /*
4372    * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then 
4373    * decode it, otherwise just dump the octet sequence 
4374    *
4375    * also, store IOR in our objectkey hash
4376    *
4377    * TODO - handle other TAGS
4378    */
4379
4380   switch(pidtag) {
4381   case IOP_TAG_INTERNET_IOP:
4382     
4383     decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4384     break;
4385
4386   default:
4387     
4388     /* fetch all octets in this sequence , but skip endianess */
4389       
4390     get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4391       
4392     /* Make a printable string */
4393       
4394     p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4395       
4396     if(tree) {
4397       proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4398                            "Profile Data: %s", p_profile_data);
4399     }
4400       
4401     g_free(p_profile_data);
4402
4403     g_free(profile_data);
4404
4405     break;
4406       
4407   }
4408
4409 }
4410
4411
4412
4413 /*
4414  * Decode IIOP IOR Profile
4415  * Ref Chap 15.7.2 in Corba Spec
4416  */
4417
4418
4419 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4420                                     guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4421                                     gboolean store_flag) {
4422
4423   guint32 i;                    /* loop index */
4424
4425   guint8 v_major,v_minor;       /* IIOP sersion */
4426   gchar *buf;
4427   guint32 u_octet4;             /* u long */
4428   guint16 u_octet2;             /* u short */
4429   guint32 seqlen;               /* generic sequence length */
4430   guint32 seqlen1;              /* generic sequence length */
4431   gchar *objkey;                /* object key pointer */
4432   gchar *p_chars;               /* printable characters pointer */
4433
4434   
4435   /* Get major/minor version */
4436
4437   v_major = get_CDR_octet(tvb,offset);
4438   v_minor = get_CDR_octet(tvb,offset);
4439
4440
4441   if (tree) {    
4442     proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4443                         *offset-sizeof(v_minor)-sizeof(v_major),1,v_major  );
4444     proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4445                         *offset-sizeof(v_minor),1,v_minor  );
4446   }
4447
4448
4449   /* host */
4450   
4451   u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4452    
4453   if (tree) {    
4454     proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4455                         *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4456     if (u_octet4 > 0) {
4457       proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4458                             *offset-u_octet4,u_octet4,buf);
4459     }
4460   }
4461   
4462   g_free(buf);          /* dont forget */
4463     
4464   /* Port */
4465
4466   u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4467
4468   if (tree) {    
4469     proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4470                         *offset-sizeof(u_octet2),2,u_octet2);
4471   }
4472
4473
4474   /* Object Key - sequence<octet> object_key */
4475
4476   seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4477
4478   if (tree) {
4479     proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4480                         *offset-sizeof(seqlen),4,seqlen);
4481   }
4482
4483   if (seqlen > 0) {
4484     /* fetch all octets in this sequence */  
4485     get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4486
4487     /*
4488      * Now we may have the Repository ID from earlier, as well
4489      * as the object key sequence and lengh. So lets store them in
4490      * our objectkey hash and free buffers.
4491      *
4492      * But only insert if user is not clicking and repo id not NULL.
4493      *
4494      */
4495
4496     if (repo_id_buf) {
4497       if (pinfo) {
4498         if(!pinfo->fd->flags.visited)
4499           insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res); 
4500       }
4501       else {
4502  
4503         /*
4504          * No pinfo, but store anyway if flag set. eg: IOR read from file
4505          */
4506
4507         if (store_flag)
4508           insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file); 
4509       }
4510     }
4511
4512     /* Make a printable string */
4513   
4514     p_chars = make_printable_string( objkey, seqlen );
4515   
4516     if(tree) {
4517       proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
4518                          "Object Key: %s", p_chars);
4519     }
4520
4521     g_free(p_chars);
4522     g_free(objkey);  
4523   }
4524   
4525   /*
4526    * Now see if if its v1.1 or 1.2, as they can contain
4527    * extra sequence of IOP::TaggedComponents
4528    *
4529    */
4530   
4531   switch(v_minor) {
4532   case 0:
4533
4534     /* nothing extra */
4535     break;
4536
4537   case 1:
4538   case 2:
4539
4540     /* sequence of IOP::TaggedComponents */
4541     /* Ref Chap 13 in Corba Spec */
4542
4543     /* get sequence length */
4544     seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4545
4546     if (tree) {
4547       proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4548                           *offset-sizeof(seqlen),4,seqlen);
4549     }
4550
4551     for (i=0; i< seqlen; i++) {
4552       /* get tag */
4553       u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4554       if (tree) {
4555         proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4556                             *offset-sizeof(u_octet4),4,u_octet4);
4557       }
4558
4559       /* get component_data */
4560       seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4561       if (tree) {
4562         proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4563                             *offset-sizeof(seqlen1),4,seqlen1);
4564       }
4565
4566       if (seqlen1 > 0) {
4567         get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4568
4569         if (tree) {
4570           /* Make a printable string of data */
4571   
4572           p_chars = make_printable_string(buf, seqlen1);
4573   
4574           proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4575                                "component_data: %s", p_chars);
4576   
4577           g_free(p_chars);
4578         }
4579
4580         g_free(buf);
4581       }
4582
4583     }
4584
4585
4586     break;
4587
4588   default:
4589     g_warning("giop:Invalid v_minor value = %u ", v_minor);
4590     break;
4591   }
4592   
4593 }
4594
4595
4596 /* 
4597  * Service Contexts Begin
4598  *
4599  */
4600
4601
4602
4603
4604
4605 #if 0
4606 void dissect_SID_BI_DIR_IIOP(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4607                                MessageHeader *header, gchar *operation, guint32 boundary) {
4608
4609   return;
4610
4611 };
4612
4613 #endif
4614
4615
4616 /*
4617  * Service Contexts End
4618  *
4619  */
4620
4621
4622
4623
4624 /*
4625  * Corba , chp 13.7
4626  *
4627  *
4628  *
4629  *      typedef unsigned long ServiceID;
4630  *
4631  *      struct ServiceContext {
4632  *              ServiceID context_id;
4633  *              sequence <octet> context_data;
4634  *      };
4635  *      typedef sequence <ServiceContext> ServiceContextList;
4636  *
4637  *
4638  * Note: Spec says context_data is an encapsulation.
4639  *
4640  *
4641  */
4642
4643
4644
4645 void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *ptree, int *offset,
4646                                gboolean stream_is_be, guint32 boundary) {
4647
4648   guint32 seqlen;               /* sequence length  */
4649   guint32 seqlen_cd;            /* sequence length, context_data  */
4650
4651   proto_tree *tree = NULL;      /* ServiceContext tree */
4652   proto_item *tf;
4653
4654   guint32 context_id;
4655   gchar *context_data;
4656   gchar *p_context_data;
4657
4658   guint32 i;
4659   guint32 vscid;                /* Vendor Service context id */
4660   guint32 scid;
4661
4662   /* create a subtree */
4663
4664   if (ptree) {
4665     tf = proto_tree_add_text (ptree, tvb, *offset, -1, "ServiceContextList");
4666     tree = proto_item_add_subtree (tf, ett_giop_scl);
4667   }
4668
4669   /* Get sequence length (number of elements) */
4670   
4671   seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4672   if (tree) {
4673     proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4674                         *offset-sizeof(seqlen),4,seqlen);
4675   }
4676
4677   /* return if zero length sequence */
4678
4679   if(seqlen == 0)
4680     return;
4681      
4682   /* Loop for all ServiceContext's */
4683
4684   for (i=0; i<seqlen; i++) {
4685
4686     context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4687     if (tree) {
4688       proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4689                           *offset-sizeof(context_id),4,context_id);
4690
4691       proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4692                           *offset-sizeof(context_id),4,context_id);
4693
4694     }
4695  
4696     vscid = context_id && 0xfffff000; /* vendor info, top 20 bits */
4697     scid = context_id  && 0x00000fff; /* standard service info, lower 12 bits */
4698
4699
4700 #if CONTEXT_DATA_IS_ENCAPSULATED
4701
4702     /* get sequence length, new endianness and boundary for encapsulation */
4703   
4704     seqlen_cd = get_CDR_encap_info(tvb, tree, offset, 
4705                                stream_is_be, boundary,
4706                                &new_big_endianess, &new_boundary);
4707
4708
4709 #else
4710    /* get sequence length, and NO  encapsulation */
4711
4712     seqlen_cd = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4713
4714 #endif
4715
4716     /* return if zero length sequence */
4717
4718     if(seqlen_cd == 0)
4719       return;
4720     
4721     /*
4722      * Now decode sequence according to vendor ServiceId, but I dont
4723      * have that yet, so just dump it as data.
4724      */    
4725
4726     /* fetch all octets in this sequence */
4727   
4728     get_CDR_octet_seq(tvb, &context_data, offset, seqlen_cd);
4729
4730     /* Make a printable string */
4731   
4732     p_context_data = make_printable_string( context_data, seqlen_cd );
4733   
4734     if(tree) {
4735       proto_tree_add_text (tree, tvb, *offset - seqlen_cd , seqlen_cd,
4736                            "context_data: %s", p_context_data);
4737     }
4738
4739     g_free(context_data);
4740     g_free(p_context_data);
4741
4742   } /* seqlen  */
4743
4744
4745   return;                       /* for now, fix later */
4746     
4747
4748 }
4749
4750 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
4751  */
4752
4753 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
4754                                              gboolean stream_is_big_endian,
4755                                              guint32 boundary) {
4756
4757   guint32 length;            /* string length */
4758   guint32 minor_code_value;
4759   guint32 completion_status;
4760
4761   gchar *buf;                /* pointer to string buffer */ 
4762
4763   length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
4764
4765   if (tree) {
4766     proto_tree_add_text(tree, tvb, *offset-4, 4,
4767                         "Exception length: %u", length);
4768     if (length > 0) {
4769       proto_tree_add_text(tree, tvb, *offset - length, length,
4770                           "Exception id: %s", buf );
4771     }
4772   }
4773   g_free(buf);
4774
4775   minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4776   completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4777         
4778   if (tree) {
4779     proto_tree_add_text(tree, tvb, *offset-8, 4,
4780                         "Minor code value: %u", minor_code_value);
4781     proto_tree_add_text(tree, tvb, *offset-4, 4,
4782                         "Completion Status: %u", completion_status);
4783   }
4784 }
4785
4786
4787 /*
4788  * Helper functions for dissecting TypeCodes 
4789  *
4790  * These functions decode the complex parameter lists
4791  * of TypeCodes as defined in the CORBA spec chapter 15.
4792  */
4793
4794 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
4795                                      gboolean stream_is_big_endian, guint32 boundary) {
4796
4797   guint32  new_boundary;             /* new boundary for encapsulation */
4798   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4799
4800   guint32 seqlen;   /* sequence length */
4801
4802   /* get sequence length, new endianness and boundary for encapsulation */
4803   seqlen = get_CDR_encap_info(tvb, tree, offset, 
4804                                    stream_is_big_endian, boundary,
4805                                    &new_stream_is_big_endian, &new_boundary);
4806
4807   /* get repository ID */
4808   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4809                                 hf_giop_repoid);
4810
4811   /* get name */
4812   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4813                                 hf_giop_typecode_name);
4814
4815 }
4816
4817
4818 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
4819                                      gboolean stream_is_big_endian, guint32 boundary,
4820                                      MessageHeader * header ) {
4821
4822   guint32  new_boundary;             /* new boundary for encapsulation */
4823   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4824
4825   guint32 count;    /* parameter count (of tuples)  */
4826   guint32 seqlen;   /* sequence length */
4827   guint32 i;        /* loop index */
4828
4829   /* get sequence lengt,h new endianness and boundary for encapsulation */
4830   seqlen = get_CDR_encap_info(tvb, tree, offset, 
4831                                    stream_is_big_endian, boundary,
4832                                    &new_stream_is_big_endian, &new_boundary);
4833
4834   /* get repository ID */
4835   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4836                                 hf_giop_repoid);
4837
4838   /* get name */
4839   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4840                                 hf_giop_typecode_name);
4841
4842   /* get count of tuples */
4843   count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4844   if (tree) {
4845     proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4846                         *offset-sizeof(count),4,count);
4847   }
4848
4849   /* get all tuples */
4850   for (i=0; i< count; i++) {
4851     /* get member name */
4852     dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4853                                   hf_giop_typecode_member_name);
4854
4855     /* get member type */
4856     get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4857   }
4858
4859 }
4860
4861
4862 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
4863                                     gboolean stream_is_big_endian, guint32 boundary,
4864                                     MessageHeader * header) {
4865
4866   guint32  new_boundary;             /* new boundary for encapsulation */
4867   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4868
4869   guint32  TCKind;    /* TypeCode */
4870   gint32   s_octet4;  /* signed int32 */
4871
4872   guint32 count;    /* parameter count (of tuples)  */
4873   guint32 seqlen;   /* sequence length */
4874   guint32 i;        /* loop index */
4875
4876   /* get sequence legnth, new endianness and boundary for encapsulation */
4877   seqlen = get_CDR_encap_info(tvb, tree, offset, 
4878                                    stream_is_big_endian, boundary,
4879                                    &new_stream_is_big_endian, &new_boundary);
4880
4881   /* get repository ID */
4882   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4883                                 hf_giop_repoid);
4884
4885   /* get name */
4886   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4887                                 hf_giop_typecode_name);
4888
4889   /* get discriminant type */
4890   TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4891
4892   /* get default used */
4893   s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
4894   if (tree) {
4895     proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
4896                         *offset-sizeof(s_octet4),4,s_octet4);
4897   }
4898   /* get count of tuples */
4899   count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4900   if (tree) {
4901     proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4902                         *offset-sizeof(count),4,count);
4903   }
4904
4905   /* get all tuples */
4906   for (i=0; i< count; i++) {
4907     /* get label value, based on TCKind above  */
4908     dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
4909
4910     /* get member name */
4911     dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4912                                   hf_giop_typecode_member_name);
4913
4914     /* get member type */
4915     get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4916   }
4917
4918 }
4919
4920
4921 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
4922                                    gboolean stream_is_big_endian, guint32 boundary) {
4923
4924   guint32  new_boundary;             /* new boundary for encapsulation */
4925   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4926
4927   guint32 count;    /* parameter count (of tuples)  */
4928   guint32 seqlen;   /* sequence length */
4929   guint32 i;        /* loop index */
4930
4931   /* get sequence length, new endianness and boundary for encapsulation */
4932   seqlen = get_CDR_encap_info(tvb, tree, offset, 
4933                                    stream_is_big_endian, boundary,
4934                                    &new_stream_is_big_endian, &new_boundary);
4935
4936   /* get repository ID */
4937   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4938                                 hf_giop_repoid);
4939
4940   /* get name */
4941   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4942                                 hf_giop_typecode_name);
4943
4944   /* get count of tuples */
4945   count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4946   if (tree) {
4947     proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4948                         *offset-sizeof(count),4,count);
4949   }
4950
4951   /* get all tuples */
4952   for (i=0; i< count; i++) {
4953     /* get member name */
4954     dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4955                                   hf_giop_typecode_member_name);
4956   }
4957
4958 }
4959
4960
4961 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
4962                                        gboolean stream_is_big_endian, guint32 boundary,
4963                                        MessageHeader * header) {
4964
4965   guint32  new_boundary;             /* new boundary for encapsulation */
4966   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4967
4968   guint32 u_octet4; /* unsigned int32 */
4969
4970   guint32 seqlen;   /* sequence length */
4971
4972   /* get sequence length, new endianness and boundary for encapsulation */
4973   seqlen = get_CDR_encap_info(tvb, tree, offset, 
4974                                    stream_is_big_endian, boundary,
4975                                    &new_stream_is_big_endian, &new_boundary);
4976
4977   /* get element type */
4978   get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4979
4980   /* get max length */
4981   u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4982   if (tree) {
4983     proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
4984                         *offset-sizeof(u_octet4),4,u_octet4);
4985   }
4986 }
4987
4988
4989 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
4990                                     gboolean stream_is_big_endian, guint32 boundary,
4991                                     MessageHeader * header) {
4992
4993   guint32  new_boundary;             /* new boundary for encapsulation */
4994   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4995
4996   guint32 u_octet4; /* unsigned int32 */
4997
4998   guint32 seqlen;   /* sequence length */
4999
5000   /* get sequence length, new endianness and boundary for encapsulation */
5001   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5002                                    stream_is_big_endian, boundary,
5003                                    &new_stream_is_big_endian, &new_boundary);
5004
5005   /* get element type */
5006   get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5007
5008   /* get length */
5009   u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5010   if (tree) {
5011     proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5012                         *offset-sizeof(u_octet4),4,u_octet4);
5013   }
5014 }
5015
5016
5017 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5018                                     gboolean stream_is_big_endian, guint32 boundary,
5019                                     MessageHeader * header) {
5020
5021   guint32  new_boundary;             /* new boundary for encapsulation */
5022   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5023
5024   guint32 seqlen;   /* sequence length */
5025
5026   /* get sequence legnth, new endianness and boundary for encapsulation */
5027   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5028                                    stream_is_big_endian, boundary,
5029                                    &new_stream_is_big_endian, &new_boundary);
5030
5031   /* get repository ID */
5032   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5033                                 hf_giop_repoid);
5034
5035   /* get name */
5036   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5037                                 hf_giop_typecode_name);
5038
5039   /* get ??? (noname) TypeCode */
5040   get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5041
5042 }
5043
5044
5045 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5046                                      gboolean stream_is_big_endian, guint32 boundary,
5047                                      MessageHeader * header) {
5048
5049   guint32  new_boundary;             /* new boundary for encapsulation */
5050   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5051
5052   guint32 count;    /* parameter count (of tuples)  */
5053   guint32 seqlen;   /* sequence length */
5054   guint32 i;        /* loop index */
5055
5056   /* get sequence length, new endianness and boundary for encapsulation */
5057   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5058                                    stream_is_big_endian, boundary,
5059                                    &new_stream_is_big_endian, &new_boundary);
5060
5061   /* get repository ID */
5062   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5063                                 hf_giop_repoid);
5064
5065   /* get name */
5066   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5067                                 hf_giop_typecode_name);
5068
5069   /* get count of tuples */
5070   count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5071   if (tree) {
5072     proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5073                         *offset-sizeof(count),4,count);
5074   }
5075
5076   /* get all tuples */
5077   for (i=0; i< count; i++) {
5078     /* get member name */
5079     dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5080                                   hf_giop_typecode_member_name);
5081
5082     /* get member type */
5083     get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5084   }
5085
5086 }
5087
5088
5089 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5090                                     gboolean stream_is_big_endian, guint32 boundary,
5091                                     MessageHeader * header) {
5092
5093   guint32  new_boundary;             /* new boundary for encapsulation */
5094   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5095
5096   gint16  s_octet2; /* signed int16 */
5097
5098   guint32 count;    /* parameter count (of tuples)  */
5099   guint32 seqlen;   /* sequence length */
5100   guint32 i;        /* loop index */
5101
5102   /* get sequence length, new endianness and boundary for encapsulation */
5103   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5104                                    stream_is_big_endian, boundary,
5105                                    &new_stream_is_big_endian, &new_boundary);
5106
5107   /* get repository ID */
5108   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5109                                 hf_giop_repoid);
5110
5111   /* get name */
5112   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5113                                 hf_giop_typecode_name);
5114
5115   /* get ValueModifier */
5116   s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5117   if (tree) {
5118     proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5119                        *offset-sizeof(s_octet2),2,s_octet2);
5120   }
5121
5122   /* get conrete base */
5123   get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5124
5125   /* get count of tuples */
5126   count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5127   if (tree) {
5128     proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5129                         *offset-sizeof(count),4,count);
5130   }
5131
5132   /* get all tuples */
5133   for (i=0; i< count; i++) {
5134     /* get member name */
5135     dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5136                                   hf_giop_typecode_member_name);
5137
5138     /* get member type */
5139     get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5140
5141     /* get Visibility */
5142     s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5143     if (tree) {
5144       proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5145                           *offset-sizeof(s_octet2),2,s_octet2);
5146     }
5147   }
5148
5149 }
5150
5151
5152 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5153                                         gboolean stream_is_big_endian, guint32 boundary,
5154                                         MessageHeader * header) {
5155
5156   guint32  new_boundary;             /* new boundary for encapsulation */
5157   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5158
5159   guint32 seqlen;   /* sequence length */
5160
5161   /* get sequence length, new endianness and boundary for encapsulation */
5162   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5163                                    stream_is_big_endian, boundary,
5164                                    &new_stream_is_big_endian, &new_boundary);
5165
5166   /* get repository ID */
5167   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5168                                 hf_giop_repoid);
5169
5170   /* get name */
5171   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5172                                 hf_giop_typecode_name);
5173
5174   /* get ??? (noname) TypeCode */
5175   get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5176 }
5177
5178
5179 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5180                                      gboolean stream_is_big_endian, guint32 boundary) {
5181
5182   guint32  new_boundary;             /* new boundary for encapsulation */
5183   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5184
5185   guint32 seqlen;   /* sequence length */
5186
5187   /* get sequence length, new endianness and boundary for encapsulation */
5188   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5189                                    stream_is_big_endian, boundary,
5190                                    &new_stream_is_big_endian, &new_boundary);
5191
5192   /* get repository ID */
5193   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5194                                 hf_giop_repoid);
5195
5196   /* get name */
5197   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5198                                 hf_giop_typecode_name);
5199
5200 }
5201
5202
5203 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5204                                                  gboolean stream_is_big_endian, guint32 boundary) {
5205
5206   guint32  new_boundary;              /* new boundary for encapsulation */
5207   gboolean new_stream_is_big_endian;  /* new endianness for encapsulation */
5208
5209   guint32 seqlen;   /* sequence length */
5210
5211   /* get sequence length, new endianness and boundary for encapsulation */
5212   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5213                                    stream_is_big_endian, boundary,
5214                                    &new_stream_is_big_endian, &new_boundary);
5215
5216   /* get repository ID */
5217   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5218                                 hf_giop_repoid);
5219
5220   /* get name */
5221   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5222                                 hf_giop_typecode_name);
5223
5224 }
5225
5226 /* Typecode parameter lists are encoded as encapsulations and
5227  * this function gets the encapsulation information; see
5228  * CORBA spec chapter 15 
5229  *
5230  *
5231  * Renamed to get_CDR_encap_info() for any encapsulation 
5232  * we come across, useful helper function 
5233  *
5234  * Also, should return immediately if seqlen == 0.
5235  * ie: Forget about trying to grab endianess for
5236  *     zero length sequence.
5237  *
5238  * Caller must always check seqlen == 0, and not assume its value
5239  *
5240  *
5241  * Note: there seemed to be considerable confusion in corba
5242  * circles as to the correct interpretation of encapsulations,
5243  * and zero length sequences etc, but this is our best bet at the 
5244  * moment.
5245  *
5246  * -- FS
5247  *
5248  */
5249
5250 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5251                        gboolean old_stream_is_big_endian, guint32 old_boundary,
5252                        gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5253  
5254   guint32 seqlen;   /* sequence length */
5255   guint8  giop_endianess;
5256
5257   /* Get sequence length of parameter list */
5258   seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5259   if (tree) {
5260     proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5261                         *offset-sizeof(seqlen),4,seqlen);
5262   }
5263
5264   
5265
5266   /*
5267    * seqlen == 0, implies no endianess and no data
5268    * so just return. Populate new_boundary_ptr and
5269    * new_stream_is_big_endian_ptr with current (old)
5270    * values, just to keep everyone happy. -- FS
5271    *
5272    */
5273
5274   if (seqlen == 0) {
5275
5276     *new_boundary_ptr = old_boundary;
5277     *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5278
5279     return seqlen;
5280
5281   }
5282
5283   /*  Start of encapsulation of parameter list */
5284   *new_boundary_ptr = *offset;  /* remember  */
5285   giop_endianess =  get_CDR_octet(tvb,offset);
5286
5287   *new_stream_is_big_endian_ptr = ! giop_endianess;
5288
5289   /*
5290    * Glib: typedef gint   gboolean;
5291    * ie: It is not a guint8, so cannot use sizeof to correctly
5292    * highlight octet.
5293    */
5294
5295
5296   if (tree) {
5297     proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5298                         *offset-1,1,giop_endianess);
5299   }
5300
5301
5302   return seqlen;
5303
5304
5305 }
5306
5307 /* 
5308  * gets a TypeCode complex string parameter and
5309  * displays it in the relevant tree.
5310  */
5311
5312 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5313                                           gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5314
5315   guint32 u_octet4;  /* unsigned int32 */
5316   gchar *buf;        /* ptr to string buffer */
5317
5318   /* get string */
5319   u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5320    
5321   if (tree) {    
5322     proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5323                         *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5324     if (u_octet4 > 0) {
5325       proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5326     }
5327   }
5328   
5329   g_free(buf);          /* dont forget */
5330
5331 }
5332
5333 /*
5334  * For a given data type, given by a TypeCode gets the associated data
5335  * and displays it in the relevant tree.
5336  */
5337
5338 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5339                                       gboolean stream_is_big_endian, guint32 boundary,
5340                                       MessageHeader * header, guint32 data_type ) {
5341
5342   gboolean my_boolean; /* boolean */
5343
5344   gint8  s_octet1;   /* signed int8 */
5345   guint8 u_octet1;   /* unsigned int8 */
5346
5347   gint16  s_octet2;  /* signed int16 */
5348   guint16 u_octet2;  /* unsigned int16 */
5349
5350   gint32  s_octet4;  /* signed int32 */
5351   guint32 u_octet4;  /* unsigned int32 */
5352
5353   gdouble my_double; /* double */
5354   gfloat  my_float;  /* float */
5355
5356   gchar *buf = NULL;            /* ptr to string buffer */
5357
5358   /* Grab the data according to data type */
5359
5360   switch (data_type) {
5361   case tk_null:
5362     /* nothing to decode */
5363     break;
5364   case tk_void:
5365     /* nothing to decode */
5366     break;
5367   case tk_short:
5368     s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5369     if (tree) {
5370       proto_tree_add_int(tree,hf_giop_type_short,tvb,
5371                          *offset-sizeof(s_octet2),2,s_octet2);
5372     }
5373     break;
5374   case tk_long:
5375     s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5376     if (tree) {
5377       proto_tree_add_int(tree,hf_giop_type_long,tvb,
5378                          *offset-sizeof(s_octet4),4,s_octet4);
5379     }
5380     break;
5381   case tk_ushort:
5382     u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5383     if (tree) {
5384       proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5385                           *offset-sizeof(u_octet2),2,u_octet2);
5386     }
5387     break;
5388   case tk_ulong:
5389     u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5390     if (tree) {
5391       proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5392                          *offset-sizeof(u_octet4),4,u_octet4);
5393     }
5394     break;
5395   case tk_float:
5396     my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5397     if (tree) {
5398       proto_tree_add_double(tree,hf_giop_type_float,tvb,
5399                             *offset-sizeof(my_float),4,my_float);
5400     }
5401     break;
5402   case tk_double:
5403     my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5404     if (tree) {
5405       proto_tree_add_double(tree,hf_giop_type_double,tvb,
5406                             *offset-sizeof(my_double),8,my_double);
5407     }
5408     break;
5409   case tk_boolean:
5410     my_boolean = get_CDR_boolean(tvb,offset);
5411     if (tree) {
5412       proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5413                              *offset-1,1,my_boolean);
5414     }
5415     break;
5416   case tk_char:
5417     u_octet1 = get_CDR_char(tvb,offset);
5418     if (tree) {
5419       proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5420                           *offset-sizeof(u_octet1),1,u_octet1);
5421     }
5422     break;
5423   case tk_octet:
5424     u_octet1 = get_CDR_octet(tvb,offset);
5425     if (tree) {
5426       proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5427                           *offset-sizeof(u_octet1),1,u_octet1);
5428     }
5429     break;
5430   case tk_any:
5431     get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5432     break;
5433   case tk_TypeCode:
5434     get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5435     break;
5436   case tk_Principal:
5437     break;
5438   case tk_objref:
5439     break;
5440   case tk_struct:
5441     break;
5442   case tk_union:
5443     break;
5444   case tk_enum:
5445     u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5446     if (tree) {
5447       proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5448                           *offset-sizeof(u_octet4),4,u_octet4);
5449     }
5450     break;
5451   case tk_string:
5452     u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5453     if (tree) {
5454       proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5455                           *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5456       if (u_octet4 > 0) {
5457         proto_tree_add_string(tree,hf_giop_type_string,tvb,
5458                               *offset-u_octet4,u_octet4,buf);
5459       }
5460     }
5461     
5462     g_free(buf);                /* dont forget */
5463     break;
5464   case tk_sequence:
5465     break;
5466   case tk_array:
5467     break;
5468   case tk_alias:
5469     break;
5470   case tk_except:
5471     break;
5472   case tk_longlong:
5473     break;
5474   case tk_ulonglong:
5475     break;
5476   case tk_longdouble:
5477     break;
5478   case tk_wchar:
5479     s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5480     if (tree) {
5481       /*
5482        * XXX - can any of these throw an exception?
5483        * If so, we need to catch the exception and free "buf".
5484        */
5485       if (s_octet1 < 0) { /* no size to add to tree */
5486         proto_tree_add_string(tree,hf_giop_type_string,tvb,
5487                               *offset+s_octet1,(-s_octet1),buf);
5488       } else {
5489         proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5490                             *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5491         proto_tree_add_string(tree,hf_giop_type_string,tvb,
5492                               *offset-s_octet1,s_octet1,buf);
5493       }
5494     }
5495
5496     g_free(buf);              /* dont forget */
5497     break;
5498   case tk_wstring:
5499     u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5500     if (tree) {
5501       /*
5502        * XXX - can any of these throw an exception?
5503        * If so, we need to catch the exception and free "buf".
5504        */
5505        proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5506                            *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5507        proto_tree_add_string(tree,hf_giop_type_string,tvb,
5508                              *offset-u_octet4,u_octet4,buf);
5509      }
5510
5511     g_free(buf);              /* dont forget */
5512     break;
5513   case tk_fixed:
5514     break;
5515   case tk_value:
5516     break;
5517   case tk_value_box:
5518     break;
5519   case tk_native:
5520     break;
5521   case tk_abstract_interface:
5522     break;
5523   default:
5524     g_warning("giop: Unknown typecode data type %u \n", data_type);
5525   break;
5526   } /* data_type */
5527
5528 }