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