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