From Tim Potter: dissect some of the LSA RPCs stub data.
[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.51 2001/12/15 20:40:18 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 "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, "GIOP FILE IOR");
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
1744   len = g_slist_length(giop_sub_list); /* find length */
1745
1746   if (len == 0)
1747     return FALSE;
1748
1749   for (i=0; i<len; i++) {
1750     subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1751
1752     if (proto_is_protocol_enabled(subh->sub_proto)) {
1753       res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1754       if (res) {
1755         return TRUE;            /* found one, lets return */
1756       }  
1757     } /* protocol_is_enabled */
1758   } /* loop */
1759
1760   return res;                   /* result */
1761
1762 }
1763
1764
1765 /*
1766  * Find the matching repoid in the module hash and call
1767  * the dissector function if offset exists.
1768  * 
1769  *
1770  * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors 
1771  * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth". 
1772  *
1773  *
1774  *
1775  */
1776
1777 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
1778                                             MessageHeader *header, gchar *operation, gchar *repoid ) {
1779
1780   giop_sub_handle_t *subdiss = NULL; /* handle */
1781   gboolean res = FALSE;
1782   gchar *modname = NULL;
1783   struct giop_module_key module_key;
1784   struct giop_module_val *module_val = NULL;
1785
1786
1787   /*
1788    * Get top level module/interface from complete repoid 
1789    */
1790
1791   modname = get_modname_from_repoid(repoid); 
1792   if (modname == NULL) {
1793     return res;                 /* unknown module name */
1794   }
1795
1796
1797   /* Search for Module or interface name */
1798
1799   module_key.module = modname; /*  module name */
1800   module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1801
1802   if (module_val == NULL) {
1803     return res;                 /* module not registered */
1804   }
1805   
1806   subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
1807
1808   if (subdiss) {
1809     /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
1810     /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
1811     /* but only if user not clicking */
1812
1813     if (!pinfo->fd->flags.visited)
1814       add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
1815
1816
1817     /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
1818
1819     if (tvb_offset_exists(tvb, *offset)) {   
1820 #if DEBUG  
1821       printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name  , modname);
1822 #endif
1823
1824       if (proto_is_protocol_enabled(subdiss->sub_proto)) {
1825
1826         res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
1827
1828       } /* protocol_is_enabled */
1829     } /* offset exists */
1830   } /* subdiss */
1831   
1832   return res;                   /* return result */
1833 }
1834
1835
1836
1837 /* Take in an array of char and create a new string.
1838  * Replace non-printable characters with periods.
1839  *
1840  * The array may contain \0's so dont use strdup
1841  * The string is \0 terminated, and thus longer than
1842  * the initial sequence. 
1843  * Caller must free the new string.
1844  */
1845
1846 static gchar * make_printable_string (gchar *in, guint32 len) {
1847   guint32 i = 0;
1848   gchar *print_string = NULL;
1849
1850   print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
1851   memcpy(print_string, in, len);        /* and make a copy of input data */
1852   
1853   for(i=0; i < len; i++) {
1854     if( !isprint( (unsigned char)print_string[i] ) ) 
1855       print_string[i] = '.';
1856   }
1857
1858   return print_string;          /* return ptr */
1859 }
1860
1861 /* Determine the byte order from the GIOP MessageHeader */
1862
1863 gboolean is_big_endian (MessageHeader * header) {
1864   gboolean big_endian = FALSE;
1865
1866   switch (header->GIOP_version.minor) {
1867   case 2:
1868   case 1:
1869     if (header->flags & 0x01)
1870       big_endian = FALSE;
1871     else
1872       big_endian = TRUE;
1873     break;
1874   case 0:
1875     if (header->flags)
1876       big_endian = FALSE;
1877     else
1878       big_endian = TRUE;
1879     break;
1880   default:
1881     break;
1882   }
1883   return big_endian;
1884 }
1885
1886
1887
1888 /* 
1889  * Calculate new offset, based on the current offset, and user supplied 
1890  * "offset delta" value, and the alignment requirement.
1891  *
1892  *
1893  *
1894  * eg: Used for GIOP 1.2 where Request and Reply bodies are 
1895  *     aligned on 8 byte boundaries.
1896  */
1897
1898 static void set_new_alignment(int *offset, int delta, int  alignment) {
1899
1900   while( ( (*offset + delta) % alignment) != 0)
1901           ++(*offset);
1902
1903
1904 }
1905
1906
1907
1908 /*
1909  * ------------------------------------------------------------------------------------------+ 
1910  *                                 Public get_CDR_xxx functions.
1911  * ------------------------------------------------------------------------------------------+
1912  */
1913
1914
1915
1916 /*
1917  * Gets data of type any. This is encoded as a TypeCode
1918  * followed by the encoded value.
1919  */
1920
1921 void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
1922                  gboolean stream_is_big_endian, int boundary,
1923                  MessageHeader * header ) {
1924   
1925   guint32  TCKind;    /* TypeCode */
1926
1927   /* get TypeCode of any */
1928   TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
1929
1930   /* dissect data of type TCKind */
1931   dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
1932 }
1933
1934
1935 /* Copy a 1 octet sequence from the tvbuff 
1936  * which represents a boolean value, and convert
1937  * it to a boolean value.
1938  * Offset is then incremented by 1, to indicate the 1 octet which
1939  * has been processed.
1940  */
1941
1942 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
1943   guint8 val;
1944
1945   val = tvb_get_guint8(tvb, *offset); /* easy */
1946   (*offset)++;
1947   return val;
1948 }
1949
1950 /* Copy a 1 octet sequence from the tvbuff 
1951  * which represents a char, and convert
1952  * it to an char value.
1953  * offset is then incremented by 1, to indicate the 1 octet which
1954  * has been processed.
1955  */
1956
1957 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
1958   guint8 val;
1959
1960   val = tvb_get_guint8(tvb, *offset); /* easy */
1961   (*offset)++;
1962   return val;
1963 }
1964
1965
1966
1967 /* 
1968  * Floating Point Data Type double IEEE 754-1985 
1969  *
1970  * Copy an 8 octet sequence from the tvbuff 
1971  * which represents a double value, and convert
1972  * it to a double value, taking into account byte order.
1973  * offset is first incremented so that it falls on a proper alignment
1974  * boundary for double values.
1975  * offset is then incremented by 8, to indicate the 8 octets which
1976  * have been processed.
1977  */
1978
1979 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
1980
1981   guint8 sign;
1982   guint8 e1,e2,f1,f2,f3,f4,f5,f6,f7;
1983   gdouble val;
1984   guint16 exp;
1985   guint32 fract0, fract1;
1986   gdouble d_fract;              
1987   
1988
1989   /* double values must be aligned on a 8 byte boundary */
1990
1991   while( ( (*offset + boundary) % 8) != 0)
1992           ++(*offset);
1993
1994
1995   if(stream_is_big_endian) {    
1996     e1  = get_CDR_octet(tvb,offset);
1997     sign = e1 >> 7;                     /* sign value */
1998     e1 &= 0x7f;         /* bottom 7 bits */
1999     f1  = get_CDR_octet(tvb,offset);
2000     e2 = f1 >> 4;
2001     f1 &= 0x0f;         /* bottom 4 bits */
2002     f2  = get_CDR_octet(tvb,offset);
2003     f3  = get_CDR_octet(tvb,offset);
2004     f4  = get_CDR_octet(tvb,offset);
2005     f5  = get_CDR_octet(tvb,offset);
2006     f6  = get_CDR_octet(tvb,offset);
2007     f7  = get_CDR_octet(tvb,offset);
2008
2009   } else {
2010
2011     f7  = get_CDR_octet(tvb,offset);
2012     f6  = get_CDR_octet(tvb,offset);
2013     f5  = get_CDR_octet(tvb,offset);
2014     f4  = get_CDR_octet(tvb,offset);
2015     f3  = get_CDR_octet(tvb,offset);
2016     f2  = get_CDR_octet(tvb,offset);
2017     f1  = get_CDR_octet(tvb,offset);
2018     e2 = f1 >> 4;
2019     f1 &= 0x0f;         /* bottom 4 bits */
2020     e1  = get_CDR_octet(tvb,offset);
2021     sign = e1 >> 7;                     /* sign value */
2022     e1 &= 0x7f;         /* bottom 7 bits */
2023
2024   }
2025
2026   exp = (e1 << 4) + e2;
2027
2028   /* Now lets do some 52 bit math with 32 bit constraint */
2029
2030   fract0 = f7 + (f6 << 8) + (f5 << 16) + (f4 << 24); /* lower 32 bits of fractional part */
2031   fract1 = f3 + (f2 << 8) + (f1 << 16);              /* top 20 bits of fractional part   */
2032
2033   d_fract = (fract1 / (pow(2,20))) + (fract0 / (pow(2,52))); /* 52 bits represent a fraction */
2034
2035   val = pow(-1,sign) * pow(2,(exp - 1023)) * (1 + d_fract);
2036
2037   return val;           /* FIX rounding ?? */
2038
2039 }
2040
2041
2042 /* Copy a 4 octet sequence from the tvbuff 
2043  * which represents an enum value, and convert
2044  * it to an enum value, taking into account byte order.
2045  * offset is first incremented so that it falls on a proper alignment
2046  * boundary for an enum (4)
2047  * offset is then incremented by 4, to indicate the 4 octets which
2048  * have been processed.
2049  *
2050  * Enum values are encoded as unsigned long.
2051  */
2052
2053
2054 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2055
2056   return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2057
2058 }
2059
2060
2061 /*
2062  * Copy an octet sequence from the tvbuff
2063  * which represents a Fixed point decimal type, and create a string representing
2064  * a Fixed point decimal type. There are no alignment restrictions.
2065  * Size and scale of fixed decimal type is determined by IDL.
2066  * 
2067  * digits - IDL specified number of "digits" for this fixed type
2068  * scale  - IDL specified "scale" for this fixed type
2069  *
2070  *
2071  * eg: typedef fixed <5,2> fixed_t;
2072  *     could represent numbers like 123.45, 789.12, 
2073  *
2074  *
2075  * As the fixed type could be any size, I will not try to fit it into our
2076  * simple types like gdouble or glong etc. I will just create a string buffer holding
2077  * a  representation (after scale is applied), and with a decimal point or zero padding
2078  * inserted at the right place if necessary. The string is null terminated
2079  *
2080  * so string may look like 
2081  *
2082  *
2083  *  "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2084  *
2085  * According to spec, digits <= 31
2086  * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2087  * or <4,0> ?
2088  *
2089  * User must remember to free the buffer
2090  *
2091  */
2092
2093
2094 void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
2095
2096   guint8 sign;                  /* 0x0c is positive, 0x0d is negative */
2097   guint32 i ;                   /* loop */
2098   guint32 slen;                 /* number of bytes to hold digits + extra 0's if scale <0 */
2099                                 /* this does not include sign, decimal point and \0 */
2100   guint32 sindex = 0;           /* string index */
2101   gchar *tmpbuf;                /* temp buff, holds string without scaling */
2102   guint8 tval;                  /* temp val storage */
2103
2104   /*
2105    * how many bytes to hold digits and scale (if scale <0) 
2106    *
2107    * eg: fixed <5,2> = 5 digits
2108    *     fixed <5,-2> = 7 digits (5 + 2 added 0's)
2109    */
2110
2111 #if DEBUG
2112     printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2113 #endif
2114
2115   if (scale <0) {
2116     slen = digits - scale;      /* allow for digits + padding 0's for negative scal */
2117   } else {
2118     slen = digits;              /*  digits */
2119   }
2120
2121 #if DEBUG
2122     printf("giop:get_CDR_fixed(): slen =  %.2x \n", slen);
2123 #endif
2124   
2125   tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */ 
2126
2127   /*
2128    * Register a cleanup function in case on of our tvbuff accesses
2129    * throws an exception. We need to clean up tmpbuf.
2130    */
2131   CLEANUP_PUSH(g_free, tmpbuf);
2132
2133   /* If even , grab 1st dig */
2134
2135   if (!(digits & 0x01)) {
2136     tval = get_CDR_octet(tvb,offset);
2137 #if DEBUG
2138     printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2139 #endif
2140     tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2141     sindex++;
2142   }
2143
2144   /*
2145    * Loop, but stop BEFORE we hit last digit and sign 
2146    * if digits = 1 or 2, then this part is skipped 
2147    */
2148
2149   if (digits>2) {
2150     for(i=0; i< ((digits-1)/2 ); i++) {
2151       tval = get_CDR_octet(tvb,offset);
2152 #if DEBUG
2153       printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2154 #endif
2155       
2156       tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2157       sindex++;
2158       tmpbuf[sindex] = (tval & 0x0f)  + 0x30; /* convert bot nibble to ascii */
2159       sindex++;
2160       
2161     }
2162   } /* digits > 3 */
2163
2164 #if DEBUG
2165     printf("giop:get_CDR_fixed(): before last digit \n");
2166 #endif
2167   
2168
2169   /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
2170
2171     tval = get_CDR_octet(tvb,offset);
2172 #if DEBUG
2173     printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
2174 #endif
2175     tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
2176     sindex++;
2177
2178     sign = tval & 0x0f; /* get sign */
2179
2180     /* So now, we have all digits in an array, and the sign byte 
2181      * so lets generate a printable string, taking into account the scale
2182      * and sign values.
2183      */
2184  
2185     sindex = 0;                         /* reset */
2186     *seq = g_new0(gchar, slen + 3);     /* allocate temp buffer , including space for sign, decimal point and 
2187                                          * \0 -- TODO check slen is reasonable first */
2188 #if DEBUG
2189     printf("giop:get_CDR_fixed(): sign =  %.2x \n", sign);
2190 #endif                                  
2191     
2192     switch(sign) {
2193     case 0x0c:
2194       (*seq)[sindex] = '+';     /* put sign in first string position */
2195       break;                    
2196     case 0x0d:
2197       (*seq)[sindex] = '-';
2198       break;
2199     default:
2200       g_warning("giop: Unknown sign value in fixed type %u \n", sign);
2201       (*seq)[sindex] = '*';     /* flag as sign unkown */
2202       break;
2203     }
2204
2205     sindex++;
2206
2207     /* Add decimal point or padding 0's, depending if scale is positive or
2208      * negative, respectively
2209      */
2210
2211     if (scale>0) {
2212       for (i=0; i<digits-scale; i++) {
2213         (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */       
2214         sindex++;
2215       }
2216       
2217       (*seq)[sindex] = '.'; /* decimal point */ 
2218       sindex++;
2219       
2220       for (i=digits-scale; i<digits; i++) {
2221         (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */    
2222         sindex++;
2223       }
2224
2225       (*seq)[sindex] = '\0'; /* string terminator */    
2226
2227     } else {
2228
2229       /* negative scale, dump digits and  pad out with 0's */
2230
2231       for (i=0; i<digits-scale; i++) {
2232         if (i<digits) {
2233           (*seq)[sindex] = tmpbuf[i]; /* save digits */ 
2234         } else {
2235           (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */       
2236         }
2237         sindex++;
2238       }
2239
2240       (*seq)[sindex] = '\0'; /* string terminator */    
2241       
2242     }
2243
2244     /*
2245      * We're done with tmpbuf, so we can call the cleanup handler to free
2246      * it, and then pop the cleanup handler.
2247      */
2248     CLEANUP_CALL_AND_POP;
2249     
2250 #if DEBUG
2251     printf("giop:get_CDR_fixed(): value = %s \n", *seq);
2252 #endif
2253
2254     return; 
2255
2256 }
2257
2258
2259
2260 /*
2261  * Floating Point Data Type float IEEE 754-1985 
2262  * 
2263  * Copy an 4 octet sequence from the tvbuff 
2264  * which represents a float value, and convert
2265  * it to a float value, taking into account byte order.
2266  * offset is first incremented so that it falls on a proper alignment
2267  * boundary for float values.
2268  * offset is then incremented by 4, to indicate the 4 octets which
2269  * have been processed.
2270  */
2271
2272 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2273   
2274   guint8 sign;
2275   guint8 e1,e2,f1,f2,f3;
2276   gfloat val;
2277   guint8 exp;
2278   guint32 fract;
2279   gdouble d_fract;              
2280   
2281   /* float values must be aligned on a 4 byte boundary */
2282
2283   while( ( (*offset + boundary) % 4) != 0)
2284     ++(*offset);
2285
2286   if(stream_is_big_endian) {    
2287     e1  = get_CDR_octet(tvb,offset);
2288     sign = e1 >> 7;                     /* sign value */
2289     e1 &= 0x7f;         /* bottom 7 bits */
2290     f1  = get_CDR_octet(tvb,offset);
2291     e2 = f1 >> 7;
2292     f1 &= 0x7f;         /* bottom 7 bits */
2293     f2  = get_CDR_octet(tvb,offset);
2294     f3  = get_CDR_octet(tvb,offset);
2295
2296   } else {
2297
2298     f3  = get_CDR_octet(tvb,offset);
2299     f2  = get_CDR_octet(tvb,offset);
2300     f1  = get_CDR_octet(tvb,offset);
2301     e2 = f1 >> 7;
2302     f1 &= 0x7f;         /* bottom 7 bits */
2303     e1  = get_CDR_octet(tvb,offset);
2304     sign = e1 >> 7;                     /* sign value */
2305     e1 &= 0x7f;         /* bottom 7 bits */
2306
2307   }
2308
2309
2310   exp = (e1 << 1) + e2;
2311   fract = f3 + (f2 << 8) + (f1 << 16);
2312
2313   d_fract = fract / (pow(2,23)); /* 23 bits represent a fraction */
2314
2315   val = pow(-1,sign) * pow(2,(exp - 127)) * (1 + d_fract);
2316
2317   return val;           /* FIX rounding ?? */
2318
2319 }
2320
2321
2322 /*
2323  * Decode an Interface type, and display it on the tree.
2324  */
2325
2326 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, 
2327                        gboolean stream_is_big_endian, int boundary) {
2328
2329
2330   decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2331   
2332   return;
2333 }
2334
2335
2336 /* Copy a 4 octet sequence from the tvbuff 
2337  * which represents a signed long value, and convert
2338  * it to an signed long vaule, taking into account byte order.
2339  * offset is first incremented so that it falls on a proper alignment
2340  * boundary for long values.
2341  * offset is then incremented by 4, to indicate the 4 octets which
2342  * have been processed.
2343  */
2344
2345 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2346
2347   gint32 val;
2348
2349   /* unsigned long values must be aligned on a 4 byte boundary */
2350   while( ( (*offset + boundary) % 4) != 0)
2351           ++(*offset);
2352
2353   val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2354                                  tvb_get_letohl (tvb, *offset);
2355
2356   *offset += 4; 
2357   return val; 
2358 }
2359
2360 /*
2361  * Decode an Object type, and display it on the tree.
2362  */
2363
2364 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, 
2365                     gboolean stream_is_big_endian, int boundary) {
2366   
2367   decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
2368   
2369   return;
2370 }
2371
2372
2373 /* Copy a 1 octet sequence from the tvbuff 
2374  * which represents a octet, and convert
2375  * it to an octet value.
2376  * offset is then incremented by 1, to indicate the 1 octet which
2377  * has been processed.
2378  */
2379
2380 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
2381   guint8 val;
2382
2383   val = tvb_get_guint8(tvb, *offset); /* easy */
2384   (*offset)++;
2385   return val;
2386 }
2387
2388
2389 /* Copy a sequence of octets from the tvbuff.
2390  * Caller of this function must remember to free the 
2391  * array pointed to by seq.
2392  * This function also increments offset by len. 
2393  */
2394
2395 void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, int len) {
2396
2397   if (! tvb_bytes_exist(tvb, *offset,len)) {
2398     /*
2399      * Generate an exception, and stop processing.
2400      * We do that now, rather than after allocating the buffer, so we
2401      * don't have to worry about freeing the buffer.
2402      * XXX - would we be better off using a cleanup routine?
2403      */
2404     tvb_get_guint8(tvb, *offset + len);
2405   }
2406
2407   /*
2408    * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
2409    * do what we do now, and null-terminate the string (which also means
2410    * we don't need to zero out the entire allocation, just the last byte)?
2411    */
2412   *seq = g_new0(gchar, len + 1);
2413   tvb_memcpy( tvb, *seq, *offset, len);
2414   *offset += len;
2415 }
2416
2417
2418 /* Copy a 2 octet sequence from the tvbuff 
2419  * which represents a signed short value, and convert
2420  * it to a signed short value, taking into account byte order.
2421  * offset is first incremented so that it falls on a proper alignment
2422  * boundary for short values.
2423  * offset is then incremented by 2, to indicate the 2 octets which
2424  * have been processed.
2425  */
2426
2427 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2428
2429   gint16 val;
2430
2431   /* short values must be aligned on a 2 byte boundary */
2432   while( ( (*offset + boundary) % 2) != 0)
2433           ++(*offset);
2434
2435   val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2436                                  tvb_get_letohs (tvb, *offset);
2437
2438   *offset += 2; 
2439   return val; 
2440 }
2441
2442
2443
2444 /* Copy an octet sequence from the tvbuff 
2445  * which represents a string, and convert
2446  * it to an string value, taking into account byte order.
2447  * offset is first incremented so that it falls on a proper alignment
2448  * boundary for string values. (begins with an unsigned long LI)
2449  *
2450  * String sequence is copied to a  buffer "seq". This must
2451  * be freed by the calling program.
2452  * offset is then incremented, to indicate the  octets which
2453  * have been processed.
2454  *
2455  * returns number of octets in the sequence
2456  *
2457  * Note: This function only supports single byte encoding at the
2458  *       moment until I get a handle on multibyte encoding etc.
2459  *
2460  */
2461
2462
2463 guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian, 
2464                        int boundary ) {
2465   
2466   guint32 slength;
2467
2468   slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
2469
2470 #if 0
2471   (*offset)++;                  /* must step past \0 delimiter */
2472 #endif
2473   
2474   if (slength > 0) {
2475     get_CDR_octet_seq(tvb, seq, offset, slength);
2476   } else {
2477     *seq = g_strdup("");        /* zero-length string */
2478   }
2479
2480   return slength;               /* return length */
2481
2482 }
2483
2484 /* Process a sequence of octets that represent the 
2485  * Pseudo Object Type "TypeCode". Typecodes are used for example,
2486  * by "Any values". 
2487  * This function also increments offset to the correct position.
2488  *
2489  * It will parse the TypeCode and output data to the "tree" provided
2490  * by the user
2491  *
2492  * It returns a guint32 representing a TCKind value. 
2493  */
2494
2495 guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
2496                          gboolean stream_is_big_endian, int boundary,
2497                          MessageHeader * header ) {
2498   guint32 val;
2499
2500   gint16  s_octet2; /* signed int16 */
2501   guint16 u_octet2; /* unsigned int16 */
2502   guint32 u_octet4; /* unsigned int32 */
2503
2504   val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
2505   if (tree) {
2506     proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
2507                         *offset-sizeof(val),4,val);
2508   }
2509
2510   /* Grab the data according to Typecode Table - Corba Chapter 15 */
2511
2512   switch (val) {
2513   case tk_null: /* empty parameter list */
2514     break;
2515   case tk_void: /* empty parameter list */
2516     break;
2517   case tk_short: /* empty parameter list */
2518     break;
2519   case tk_long: /* empty parameter list */
2520     break;
2521   case tk_ushort: /* empty parameter list */
2522     break;
2523   case tk_ulong: /* empty parameter list */
2524     break;
2525   case tk_float: /* empty parameter list */
2526     break;
2527   case tk_double: /* empty parameter list */
2528     break;
2529   case tk_boolean: /* empty parameter list */
2530     break;
2531   case tk_char: /* empty parameter list */
2532     break;
2533   case tk_octet: /* empty parameter list */
2534     break;
2535   case tk_any: /* empty parameter list */
2536     break;
2537   case tk_TypeCode: /* empty parameter list */
2538     break;
2539   case tk_Principal: /* empty parameter list */
2540     break;
2541   case tk_objref: /* complex parameter list */
2542     dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2543     break;
2544   case tk_struct: /* complex parameter list */
2545     dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2546     break;
2547   case tk_union: /* complex parameter list */
2548     dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2549     break;
2550   case tk_enum: /* complex parameter list */
2551     dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2552     break;
2553
2554   case tk_string: /* simple parameter list */
2555     u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2556     if (tree) {
2557       proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2558                           *offset-sizeof(u_octet4),4,u_octet4);
2559     }
2560     break;
2561
2562   case tk_sequence: /* complex parameter list */
2563     dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2564     break;
2565   case tk_array: /* complex parameter list */
2566     dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2567     break;
2568   case tk_alias: /* complex parameter list */
2569     dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2570     break;
2571   case tk_except: /* complex parameter list */
2572     dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2573     break;
2574   case tk_longlong: /* empty parameter list */
2575     break;
2576   case tk_ulonglong: /* empty parameter list */
2577     break;
2578   case tk_longdouble: /* empty parameter list */
2579     break;
2580   case tk_wchar: /* empty parameter list */
2581     break;
2582   case tk_wstring: /* simple parameter list */
2583     u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
2584     if (tree) {
2585       proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
2586                           *offset-sizeof(u_octet4),4,u_octet4);
2587     }
2588     break;
2589
2590   case tk_fixed: /* simple parameter list */
2591     u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
2592     if (tree) {
2593       proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
2594                           *offset-sizeof(u_octet2),2,u_octet2);
2595     }
2596
2597     s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
2598     if (tree) {
2599       proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
2600                           *offset-sizeof(s_octet2),2,s_octet2);
2601     }
2602     break;
2603
2604   case tk_value: /* complex parameter list */
2605     dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2606     break;
2607   case tk_value_box: /* complex parameter list */
2608     dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2609     break;
2610   case tk_native: /* complex parameter list */
2611     dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2612     break;
2613   case tk_abstract_interface: /* complex parameter list */
2614     dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
2615     break;
2616   default:
2617     g_warning("giop: Unknown TCKind %u \n", val);
2618     break;
2619   } /* val */
2620
2621   return val;
2622 }
2623
2624
2625
2626 /* Copy a 4 octet sequence from the tvbuff 
2627  * which represents an unsigned long value, and convert
2628  * it to an unsigned long vaule, taking into account byte order.
2629  * offset is first incremented so that it falls on a proper alignment
2630  * boundary for unsigned long values.
2631  * offset is then incremented by 4, to indicate the 4 octets which
2632  * have been processed.
2633  */
2634
2635 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2636
2637   guint32 val;
2638
2639   /* unsigned long values must be aligned on a 4 byte boundary */
2640   while( ( (*offset + boundary) % 4) != 0)
2641           ++(*offset);
2642
2643   val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
2644                                  tvb_get_letohl (tvb, *offset);
2645
2646   *offset += 4; 
2647   return val; 
2648 }
2649
2650
2651 /* Copy a 2 octet sequence from the tvbuff 
2652  * which represents an unsigned short value, and convert
2653  * it to an unsigned short value, taking into account byte order.
2654  * offset is first incremented so that it falls on a proper alignment
2655  * boundary for unsigned short values.
2656  * offset is then incremented by 2, to indicate the 2 octets which
2657  * have been processed.
2658  */
2659
2660 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2661
2662   guint16 val;
2663
2664   /* unsigned short values must be aligned on a 2 byte boundary */
2665   while( ( (*offset + boundary) % 2) != 0)
2666           ++(*offset);
2667
2668   val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
2669                                  tvb_get_letohs (tvb, *offset);
2670
2671   *offset += 2; 
2672   return val; 
2673 }
2674
2675
2676
2677 /* Copy a wchar from the tvbuff.
2678  * Caller of this function must remember to free the 
2679  * array pointed to by seq.
2680  * This function also increments offset according to
2681  * the wchar size.
2682  *
2683  * For GIOP 1.1 read 2 octets and return size -2. The
2684  * negation means there is no size element in the packet
2685  * and therefore no size to add to the tree.
2686  *
2687  * For GIOP 1.2 read size of wchar and the size
2688  * octets. size is returned as a gint8.
2689  *
2690  * For both GIOP versions the wchar is returned
2691  * as a printable string.
2692  *
2693  */
2694
2695 /* NOTE: This is very primitive in that it just reads
2696  * the wchar as a series of octets and returns them
2697  * to the user. No translation is attempted based on
2698  * byte orientation, nor on code set. I.e it only 
2699  * really reads past the wchar and sets the offset
2700  * correctly.
2701  */
2702
2703 /* The "decoding" is done according to CORBA chapter 15.
2704  * Wchar is not supported for GIOP 1.0.
2705  */
2706
2707 gint8 get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
2708   
2709   gint8 slength;
2710   gchar *raw_wstring;
2711
2712   /* CORBA chapter 15:
2713    *   - prior to GIOP 1.2 wchar limited to two octet fixed length.
2714    *   - GIOP 1.2 wchar is encoded as an unsigned binary octet
2715    *     followed by the elements of the octet sequence representing
2716    *     the encoded value of the wchar.
2717    */
2718
2719   *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2720   slength = 2; /* set for GIOP 1.1 length in octets */
2721
2722   if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
2723     slength = get_CDR_octet(tvb,offset);
2724
2725   if (slength > 0) {
2726     /* ??? assume alignment is ok for GIOP 1.1 ??? */
2727     get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2728
2729     /* now turn octets (wchar) into something that can be printed by the user */
2730     *seq = make_printable_string(raw_wstring, slength);
2731
2732     g_free(raw_wstring);
2733   }
2734
2735   /* if GIOP 1.1 negate length to indicate not an item to add to tree */
2736   if (header->GIOP_version.minor < 2)
2737     slength = -slength;
2738
2739   return slength;               /* return length */
2740
2741 }
2742
2743
2744 /* Copy a wstring from the tvbuff.
2745  * Caller of this function must remember to free the 
2746  * array pointed to by seq.
2747  * This function also increments offset, according to
2748  * wstring length. length is returned as guint32
2749  */
2750
2751 /* NOTE: This is very primitive in that it just reads
2752  * the wstring as a series of octets and returns them
2753  * to the user. No translation is attempted based on
2754  * byte orientation, nor on code set. I.e it only 
2755  * really reads past the wstring and sets the offset
2756  * correctly.
2757  */
2758
2759 /* The "decoding" is done according to CORBA chapter 15.
2760  * Wstring is not supported for GIOP 1.0.
2761  */
2762
2763
2764 guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian, 
2765                        int boundary, MessageHeader * header) {
2766   
2767   guint32 slength;
2768   gchar *raw_wstring;
2769
2770   /* CORBA chapter 15:
2771    *   - prior to GIOP 1.2 wstring limited to two octet fixed length.
2772    *     length and string are NUL terminated (length???).
2773    *   - GIOP 1.2 length is total number of octets. wstring is NOT NUL
2774    *     terminated.
2775    */
2776
2777   *seq = NULL; /* set in case GIOP 1.2 length is 0 */
2778
2779   /* get length, same for all GIOP versions,
2780    * although for 1.2 CORBA doesnt say, so assume. 
2781    */
2782   slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2783
2784 #ifdef DEBUG
2785   if (slength>200) {
2786         fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
2787         slength = 5;            /* better than core dumping during debug */
2788   }
2789 #endif
2790   
2791   if (header->GIOP_version.minor < 2) {
2792 #if 0
2793     (*offset)++;  /* must step past \0 delimiter */
2794 #endif
2795     /* assume length is number of characters and not octets, spec not clear */
2796     slength = slength * 2; /* length in octets is 2 * wstring length */
2797   }
2798
2799   if (slength > 0) {
2800     get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
2801
2802     /* now turn octets (wstring) into something that can be printed by the user */
2803     *seq = make_printable_string(raw_wstring, slength);
2804
2805     g_free(raw_wstring);
2806   }
2807
2808   return slength;               /* return length */
2809
2810 }
2811
2812
2813
2814 /**
2815  *  Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
2816  *  GIOP 1.2
2817  *  typedef short AddressingDisposition;
2818  *  const short KeyAddr = 0;
2819  *  const short ProfileAddr = 1;
2820  *  const short ReferenceAddr = 2;
2821  *  struct IORAddressingInfo {
2822  *    unsigned long selected_profile_index;
2823  *    IOP::IOR ior;
2824  *  };
2825  *
2826  *  union TargetAddress switch (AddressingDisposition) {
2827  *      case KeyAddr: sequence <octet> object_key;
2828  *      case ProfileAddr: IOP::TaggedProfile profile;
2829  *      case ReferenceAddr: IORAddressingInfo ior;
2830  *  };
2831  */
2832
2833 static void
2834 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree, 
2835                        MessageHeader * header, gboolean stream_is_big_endian)
2836 {
2837    guint16 discriminant;
2838    gchar *object_key;
2839    gchar *p_object_key;
2840    guint32 len = 0;
2841    guint32 u_octet4;
2842
2843    discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2844    if(tree)
2845    {
2846      proto_tree_add_text (tree, tvb, *offset -2, 2,
2847                  "TargetAddress Discriminant: %u", discriminant);
2848    }
2849   
2850    switch (discriminant)
2851    {
2852            case 0:  /* KeyAddr */
2853                    len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2854                    if(tree)
2855                    {
2856                       proto_tree_add_text (tree, tvb, *offset -4, 4,
2857                                            "KeyAddr (object key length): %u", len);
2858                    }
2859
2860                    if (len > 0) {
2861
2862                      get_CDR_octet_seq(tvb, &object_key, offset, len);
2863                      p_object_key = make_printable_string( object_key, len );
2864                    
2865                      if(tree)
2866                        {
2867                          proto_tree_add_text (tree, tvb, *offset -len, len,
2868                                                "KeyAddr (object key): %s", p_object_key);
2869                        }
2870                      g_free( p_object_key );
2871                      g_free( object_key );
2872                    }
2873                    break;
2874            case 1: /* ProfileAddr */
2875                    decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
2876                                         stream_is_big_endian, NULL);
2877                    break;
2878            case 2: /* ReferenceAddr */
2879                    u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2880
2881                    if(tree)
2882                    {
2883                       proto_tree_add_text (tree, tvb, *offset -len -4, 4,
2884                                            "ReferenceAddr (selected_profile_index): %u", u_octet4);
2885                    }
2886
2887                    decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
2888                    break;
2889            default:
2890                    break;
2891    }
2892 }
2893
2894 static void
2895 dissect_reply_body (tvbuff_t *tvb, u_int offset, packet_info *pinfo,
2896                     proto_tree *tree, gboolean stream_is_big_endian,
2897                     guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
2898
2899   u_int sequence_length;
2900   gboolean exres = FALSE;               /* result of trying explicit dissectors */
2901   gchar * repoid = NULL;        /* Repositor ID looked up from  objkey */
2902   
2903   /*
2904    * comp_req_list stuff
2905    */
2906
2907   comp_req_list_entry_t * entry = NULL; /* data element in our list */
2908   
2909   guint32 mfn;
2910
2911   switch (reply_status)
2912     {
2913     case SYSTEM_EXCEPTION:
2914
2915       decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
2916       break;
2917
2918     case USER_EXCEPTION:
2919
2920       sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
2921
2922       if (tree)
2923       {
2924           proto_tree_add_text(tree, tvb, offset-4, 4,
2925                            "Exception length: %u", sequence_length);
2926       }
2927       if (sequence_length != 0)
2928         {
2929           if (tree)
2930           {
2931               proto_tree_add_text(tree, tvb, offset, sequence_length,
2932                            "Exception id: %s",
2933                            tvb_format_text(tvb, offset, sequence_length));
2934           }
2935 #if 1
2936
2937           header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
2938
2939           /* read exception id from buffer and store in*/
2940
2941           tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
2942           
2943
2944 #endif          
2945           
2946
2947           offset += sequence_length;
2948         }
2949
2950
2951
2952       /*
2953        * Now just fall through to the NO_EXCEPTION part
2954        * as this is common .
2955        */
2956       
2957
2958
2959     case NO_EXCEPTION:
2960
2961
2962       /* lookup MFN in hash directly */
2963  
2964       mfn = get_mfn_from_fn(pinfo->fd->num); 
2965       
2966       if (mfn == pinfo->fd->num)
2967         return;                 /* no matching frame number, what am I */
2968
2969       /* get entry for this MFN */
2970       entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
2971
2972       if (!entry)
2973         return;                 /* no matching entry */
2974         
2975
2976       /*
2977        * If this packet is a REPLY to a RESOLVE(request) 
2978        * then decode IOR.
2979        * TODO - make this lookup faster -- FS
2980        */
2981       
2982       if (!strcmp(giop_op_resolve,entry->operation)) {
2983         decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
2984         return;         /* done */
2985       }
2986       
2987       /* TODO -- Put stuff here for other "interesting operations" */
2988
2989       /*
2990        *
2991        * Call sub dissector.
2992        * First try an find a explicit sub_dissector, then if that
2993        * fails, try the heuristic method.
2994        */
2995
2996
2997       if(entry->repoid) {    
2998         exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
2999       }
3000
3001       /* Only call heuristic if no explicit dixxector was found */
3002
3003       if(! exres) {
3004         try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
3005       } 
3006
3007
3008       break;
3009       
3010     case LOCATION_FORWARD:
3011       decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3012
3013       break;
3014
3015     case LOCATION_FORWARD_PERM:
3016       decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3017
3018       break;
3019
3020     case NEEDS_ADDRESSING_MODE: {
3021       guint16 addr_disp;
3022       addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3023       if(tree) {
3024         proto_tree_add_text (tree, tvb, offset -2, 2,
3025                              "AddressingDisposition: %u", addr_disp);
3026       }
3027
3028       break;
3029     }
3030
3031     default:
3032       
3033       g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
3034       
3035       break;
3036       
3037     } /* switch */
3038   
3039   g_free(repoid);               /* free resource */
3040   
3041   return;                       /* done */
3042   
3043 }
3044
3045
3046
3047
3048
3049 /* The format of the Reply Header for GIOP 1.0 and 1.1
3050  * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
3051
3052     struct ReplyHeader_1_0 {
3053           IOP::ServiceContextList service_context;
3054           unsigned long request_id;
3055           ReplyStatusType_1_0 reply_status;
3056     };
3057  */
3058
3059 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3060                                 proto_tree * clnp_tree, MessageHeader * header,
3061                                 gboolean stream_is_big_endian) {
3062
3063   guint32 offset = 0;
3064   guint32 request_id;
3065   guint32 reply_status;
3066   proto_tree *reply_tree = NULL;
3067   proto_item *tf;
3068   guint32 mfn;                  /* matching frame number */
3069
3070   if (tree) {
3071     tf = proto_tree_add_text (tree, tvb, offset,
3072                               tvb_length (tvb),
3073                               "General Inter-ORB Protocol Reply");
3074     if (reply_tree == NULL)
3075       {
3076         reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3077         
3078       }
3079   }
3080   
3081   /*
3082    * Decode IOP::ServiceContextList
3083    */
3084   
3085   decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3086
3087   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3088
3089   if (check_col(pinfo->cinfo, COL_INFO)) {
3090     col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3091   }
3092
3093   if (tree) {
3094     proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3095                          "Request id: %u", request_id);
3096   }
3097
3098   reply_status = 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, ": %s",
3102                     val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3103
3104   }
3105
3106   if (tree) {
3107     proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3108                          "Reply status: %s",
3109                          val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3110     
3111   }
3112
3113   /*
3114    * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3115    */
3116
3117   if (! pinfo->fd->flags.visited) {
3118     mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3119     if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3120       insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3121     }
3122   }
3123
3124   header->req_id = request_id;          /* save for sub dissector */
3125   header->rep_status = reply_status;   /* save for sub dissector */
3126
3127   dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3128     reply_status, header,tree);
3129
3130
3131 }
3132
3133 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
3134  *  and 1.1 header, only the fields have been rearranged.  From Section
3135  *  15.4.3.1 of the CORBA 2.4 specification:
3136  *
3137  *   struct ReplyHeader_1_2 {
3138  *         unsigned long request_id;
3139  *         ReplyStatusType_1_2 reply_status;
3140  *         IOP:ServiceContextList service_context; 
3141  *    };
3142  */
3143
3144 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3145                                     proto_tree * tree, proto_tree * clnp_tree,
3146                                     MessageHeader * header,
3147                                     gboolean stream_is_big_endian) {
3148
3149   u_int offset = 0;
3150   guint32 request_id;
3151   guint32 reply_status;
3152   proto_tree *reply_tree = NULL;
3153   proto_item *tf;
3154   guint32 mfn;                  /* matching frame number */
3155   
3156   if (tree) {
3157     tf = proto_tree_add_text (tree, tvb, offset,
3158                               tvb_length (tvb),
3159                               "General Inter-ORB Protocol Reply");
3160     reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
3161   }
3162   
3163   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3164   
3165   if (check_col(pinfo->cinfo, COL_INFO)) {
3166     col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3167   }
3168
3169   if (tree) {
3170     proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3171                          "Request id: %u", request_id);
3172   }
3173
3174   reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3175   
3176   if (check_col(pinfo->cinfo, COL_INFO)) {
3177     col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
3178                     val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3179
3180   }
3181
3182   if (tree) {
3183     proto_tree_add_text (reply_tree, tvb, offset-4, 4,
3184                          "Reply status: %s",
3185                          val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
3186
3187   }
3188
3189   /*
3190    * Decode IOP::ServiceContextList
3191    */
3192
3193   decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3194
3195   /*
3196    * GIOP 1.2 Reply body must fall on an 8 octet alignment.
3197    */
3198
3199   set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3200
3201   /*
3202    * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
3203    */
3204   
3205   if (! pinfo->fd->flags.visited) {
3206     mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
3207     if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
3208       insert_in_complete_reply_hash(pinfo->fd->num, mfn);
3209     }
3210   }
3211
3212   /*
3213    * Add header to argument list so sub dissector can get header info.
3214    */
3215
3216   header->req_id = request_id;          /* save for sub dissector */
3217   header->rep_status = reply_status;   /* save for sub dissector */
3218
3219   dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
3220                      reply_status,header,tree);
3221
3222 }
3223
3224
3225
3226 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
3227                         proto_tree * tree, proto_tree * clnp_tree,
3228                         MessageHeader * header, gboolean stream_is_big_endian) {
3229
3230   u_int offset = 0;
3231   guint32 request_id;
3232   proto_tree *cancel_request_tree = NULL;
3233   proto_item *tf;
3234
3235   if (tree) {
3236     tf = proto_tree_add_text (tree, tvb, offset,
3237                               tvb_length (tvb),
3238                               "General Inter-ORB Protocol CancelRequest");
3239     cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
3240   }
3241
3242   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3243   
3244   if (check_col(pinfo->cinfo, COL_INFO)) {
3245     col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3246   }
3247
3248   if (tree) {
3249     proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4,
3250                          "Request id: %u", request_id);
3251   }
3252
3253   
3254 }
3255
3256 /**  The formats for GIOP 1.0 and 1.1 Request messages are defined
3257  *   in section 15.4.2.1 of the CORBA 2.4 specification.
3258  *
3259  *   struct RequestHeader{
3260  *          IOP::ServiceContextList   service_context;
3261  *          unsigned long             request_id;
3262  *          boolean                   response_expected;
3263  *          octet                     reserved[3];  // Only in GIOP 1.1
3264  *          sequence<octet>           object_key;
3265  *          string                    operation;
3266  *          CORBA::OctetSeq           requesting_principal;
3267  *   }
3268  */
3269 static void
3270 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
3271                         proto_tree * tree, proto_tree * clnp_tree,
3272                         MessageHeader * header, gboolean stream_is_big_endian)
3273 {
3274   guint32 offset = 0;
3275   guint32 request_id;
3276   guint32 len = 0;
3277
3278   guint32 objkey_len = 0;       /* object key length */
3279   gchar *objkey = NULL;         /* object key sequence */
3280   gchar *print_objkey;          /* printable object key sequence */
3281   gboolean exres = FALSE;       /* result of trying explicit dissectors */
3282
3283   gchar *operation;
3284   gchar *requesting_principal;
3285   gchar *print_requesting_principal;
3286   guint8 response_expected;
3287   gchar *reserved;
3288   proto_tree *request_tree = NULL;
3289   proto_item *tf;
3290
3291   gchar *repoid = NULL;         /* from object key lookup in objkey hash */
3292
3293
3294   if (tree)
3295     {
3296       tf = proto_tree_add_text (tree, tvb, offset,
3297                                 tvb_length (tvb),
3298                                 "General Inter-ORB Protocol Request");
3299       if (request_tree == NULL)
3300         {
3301           request_tree = proto_item_add_subtree (tf, ett_giop_request);
3302
3303         }
3304     }
3305
3306
3307
3308
3309   /*
3310    * Decode IOP::ServiceContextList
3311    */
3312   
3313   decode_ServiceContextList(tvb, pinfo, request_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
3314
3315
3316   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3317   if (check_col(pinfo->cinfo, COL_INFO))
3318     {
3319       col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3320     }
3321   if (tree)
3322     {
3323       proto_tree_add_text (request_tree, tvb, offset-4, 4,
3324                            "Request id: %u", request_id);
3325     }
3326
3327   response_expected = tvb_get_guint8( tvb, offset );
3328   offset += 1;
3329   if (check_col(pinfo->cinfo, COL_INFO))
3330     {
3331       col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3332                 response_expected ? "two-way" : "one-way");
3333     }
3334   if (tree)
3335     {
3336       proto_tree_add_text (request_tree, tvb, offset-1, 1,
3337                            "Response expected: %u", response_expected);
3338     }
3339
3340   if( header->GIOP_version.minor > 0)
3341   {
3342      get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3343      if (tree)
3344        {
3345          proto_tree_add_text (request_tree, tvb, offset-3, 3,
3346                            "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3347        }
3348      g_free(reserved);
3349   }
3350
3351
3352
3353   /* Length of object_key sequence */
3354   objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3355
3356
3357   if(tree)
3358   {
3359          proto_tree_add_text (request_tree, tvb, offset-4, 4,
3360          /**/                 "Object Key length: %u", objkey_len);
3361   } 
3362
3363   if (objkey_len > 0)
3364   {
3365        get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
3366
3367        print_objkey = make_printable_string(objkey, objkey_len);
3368
3369        if(tree)
3370        {
3371          proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
3372          /**/                 "Object Key: %s", print_objkey);
3373
3374        }
3375
3376        g_free( print_objkey );  
3377   } 
3378
3379   /*
3380    * Register a cleanup function in case on of our tvbuff accesses
3381    * throws an exception. We need to clean up objkey.
3382    */
3383   CLEANUP_PUSH(g_free, objkey);
3384
3385   /* length of operation string and string */ 
3386   len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3387   if(tree)
3388   {
3389          proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
3390          /**/                 "Operation length: %u", len);
3391   } 
3392
3393   if( len > 0)
3394   {
3395        if (check_col(pinfo->cinfo, COL_INFO))
3396        {
3397          col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3398        }
3399        if(tree)
3400        {
3401          proto_tree_add_text (request_tree, tvb, offset - len, len,
3402          /**/                 "Operation: %s", operation);
3403
3404        }
3405   }
3406
3407   /*
3408    * Register a cleanup function in case on of our tvbuff accesses
3409    * throws an exception. We need to clean up operation.
3410    */
3411   CLEANUP_PUSH(g_free, operation);
3412
3413   /* length of requesting_principal string */ 
3414   len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3415   if(tree)
3416   {
3417          proto_tree_add_text (request_tree, tvb, offset-4, 4,
3418          /**/                 "Requesting Principal Length: %u", len);
3419   } 
3420
3421   if( len > 0)
3422   {
3423        get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
3424
3425        print_requesting_principal = make_printable_string(requesting_principal, len);
3426
3427        if(tree)
3428        {
3429          proto_tree_add_text (request_tree, tvb, offset - len, len, 
3430          /**/                 "Requesting Principal: %s", print_requesting_principal);
3431
3432        }
3433
3434        g_free( print_requesting_principal );
3435        g_free( requesting_principal );
3436   }
3437
3438
3439   /*
3440    * Save FN,reqid,and operation for later. Add sub_handle later.
3441    * But only if user is NOT clicking.
3442    */
3443
3444   if (! pinfo->fd->flags.visited)
3445     giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3446                                                          request_id,operation,NULL);
3447
3448   
3449   /*
3450    * Call subdissector here before freeing "operation" and "key"
3451    * pass request_id also. 
3452    * First try an find an explicit sub_dissector, then if that
3453    * fails, try the heuristic method.
3454    *
3455    */
3456
3457
3458   header->req_id = request_id;          /* save for sub dissector */
3459   repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
3460
3461
3462   if(repoid) {    
3463     exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3464   }
3465
3466   /* Only call heuristic if no explicit dissector was found */
3467
3468   if (! exres) {
3469     try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3470   }
3471   
3472
3473   /*
3474    * We're done with operation, so we can call the cleanup handler to free
3475    * it, and then pop the cleanup handler.
3476    */
3477   CLEANUP_CALL_AND_POP;
3478
3479   /*
3480    * We're done with objkey, so we can call the cleanup handler to free
3481    * it, and then pop the cleanup handler.
3482    */
3483   CLEANUP_CALL_AND_POP;
3484
3485 }
3486
3487 /**  The format of a GIOP 1.2 RequestHeader message is 
3488  *   (CORBA 2.4, sec. 15.4.2):
3489  *
3490  *   struct RequestHeader_1_2 {
3491  *       unsigned long request_id;
3492  *       octet response_flags;
3493  *       octet reserved[3];
3494  *       TargetAddress target;
3495  *       string operation;
3496  *       IOP::ServiceContextList service_context;
3497  *       // requesting_principal not in GIOP 1.2
3498  *   };
3499  */
3500 static void
3501 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
3502                         proto_tree * tree, proto_tree * clnp_tree,
3503                         MessageHeader * header, gboolean stream_is_big_endian)
3504 {
3505   guint32 offset = 0;
3506   guint32 request_id;
3507   guint32 len = 0;
3508   guint8 response_flags;
3509   gchar *reserved;
3510   gchar *operation = NULL;
3511   proto_tree *request_tree = NULL;
3512   proto_item *tf;
3513   gboolean exres = FALSE;               /* result of trying explicit dissectors */
3514
3515   gchar *repoid = NULL;
3516
3517
3518   if (tree)
3519     {
3520       tf = proto_tree_add_text (tree, tvb, offset,
3521                                 tvb_length (tvb),
3522                                 "General Inter-ORB Protocol Request");
3523       request_tree = proto_item_add_subtree (tf, ett_giop_reply);
3524     }
3525
3526   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3527   if (check_col(pinfo->cinfo, COL_INFO))
3528     {
3529       col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3530     }
3531   if (request_tree)
3532     {
3533       proto_tree_add_text (request_tree, tvb, offset-4, 4,
3534                            "Request id: %u", request_id);
3535     }
3536
3537   response_flags = tvb_get_guint8( tvb, offset );
3538   offset += 1;
3539   if (request_tree)
3540     {
3541       proto_tree_add_text (request_tree, tvb, offset-1, 1,
3542                            "Response flags: %s (%u)",
3543                                 match_strval(response_flags, sync_scope),  
3544                                 response_flags);
3545     }
3546
3547   get_CDR_octet_seq( tvb, &reserved, &offset, 3);
3548   if (request_tree)
3549    {
3550      proto_tree_add_text (request_tree, tvb, offset-3, 3,
3551            "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
3552    }
3553   g_free(reserved);
3554
3555   dissect_target_address(tvb, pinfo, &offset, request_tree, header, stream_is_big_endian);
3556
3557   /* length of operation string */ 
3558   len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3559   if(tree)
3560   {
3561          proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
3562          /**/                 "Operation length: %u", len);
3563   } 
3564
3565   if( len > 0)
3566   {
3567        if (check_col(pinfo->cinfo, COL_INFO))
3568        {
3569          col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
3570        }
3571        if(request_tree)
3572        {
3573          proto_tree_add_text (request_tree, tvb, offset - len, len,
3574          /**/                 "Operation: %s", operation);
3575
3576        }
3577
3578   }
3579
3580   /*
3581    * Register a cleanup function in case on of our tvbuff accesses
3582    * throws an exception. We need to clean up operation.
3583    */
3584   CLEANUP_PUSH(g_free, operation);
3585
3586   /*
3587    * Decode IOP::ServiceContextList
3588    */
3589
3590   decode_ServiceContextList(tvb, pinfo, request_tree, &offset,  stream_is_big_endian, GIOP_HEADER_SIZE);
3591
3592   /*
3593    * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
3594    * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
3595    * GIOP octet stream start.
3596    */
3597
3598   set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
3599
3600   /*
3601    * Save FN,reqid,and operation for later. Add sub_handle later.
3602    * But only if user is NOT clicking.
3603    */
3604   
3605   if (! pinfo->fd->flags.visited)
3606     giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
3607                                                          request_id,operation,NULL);
3608
3609   /*
3610    *
3611    * Call sub dissector.
3612    * First try an find a explicit sub_dissector, then if that
3613    * fails, try the heuristic method.
3614    */
3615   
3616
3617   if(repoid) {    
3618     exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
3619   }
3620
3621   /* Only call heuristic if no explicit dissector was found */
3622
3623   if (! exres) {
3624     try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
3625   }
3626   
3627
3628   /*
3629    * We're done with operation, so we can call the cleanup handler to free
3630    * it, and then pop the cleanup handler.
3631    */
3632   CLEANUP_CALL_AND_POP;
3633 }
3634
3635 static void
3636 dissect_giop_locate_request( 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 len = 0;
3643   gchar *object_key;
3644   gchar *p_object_key;
3645   proto_tree *locate_request_tree = NULL;
3646   proto_item *tf;
3647
3648   if (tree)
3649     {
3650       tf = proto_tree_add_text (tree, tvb, offset,
3651                                 tvb_length (tvb),
3652                                 "General Inter-ORB Locate Request");
3653       if (locate_request_tree == NULL)
3654         {
3655           locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
3656
3657         }
3658     }
3659
3660   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3661   if (check_col(pinfo->cinfo, COL_INFO))
3662     {
3663       col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3664     }
3665   if (locate_request_tree)
3666     {
3667       proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3668                            "Request id: %u", request_id);
3669     }
3670
3671   if(header->GIOP_version.minor < 2)
3672   {
3673         len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3674         if (locate_request_tree)
3675           {
3676             proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
3677                                  "Object Key length: %u", len);
3678           }
3679
3680         if (len > 0) {
3681           get_CDR_octet_seq(tvb, &object_key, &offset, len);
3682
3683           p_object_key = make_printable_string(object_key, len);
3684   
3685           if(locate_request_tree)
3686             {
3687
3688               proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
3689                                    "Object Key: %s", p_object_key);
3690             }
3691
3692           g_free(p_object_key);
3693           g_free(object_key);
3694         }
3695   }
3696   else     /* GIOP 1.2 and higher */
3697   {
3698       dissect_target_address(tvb, pinfo, &offset, locate_request_tree, header,
3699                              stream_is_big_endian);
3700
3701   }
3702 }
3703
3704 static void
3705 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
3706                         proto_tree * tree, MessageHeader * header,
3707                         gboolean stream_is_big_endian)
3708 {
3709   guint32 offset = 0;
3710   guint32 request_id;
3711   guint32 locate_status;
3712   guint16 addr_disp;
3713
3714   proto_tree *locate_reply_tree = NULL;
3715   proto_item *tf;
3716
3717   if (tree)
3718     {
3719       tf = proto_tree_add_text (tree, tvb, offset,
3720                                 tvb_length (tvb),
3721                                 "General Inter-ORB Locate Reply");
3722       if (locate_reply_tree == NULL)
3723         {
3724           locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
3725
3726         }
3727     }
3728
3729   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3730   if (check_col(pinfo->cinfo, COL_INFO))
3731     {
3732       col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3733     }
3734   if (locate_reply_tree)
3735     {
3736       proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3737                            "Request id: %u", request_id);
3738     }
3739
3740   locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3741   if (locate_reply_tree)
3742     {
3743       proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
3744                            "Locate status: %s", 
3745                            match_strval(locate_status, giop_locate_status_types)
3746                            );
3747     }
3748
3749   /* Decode the LocateReply body.
3750    *
3751    * For GIOP 1.0 and 1.1 body immediately follows header.
3752    * For GIOP 1.2 it is aligned on 8 octet boundary so need to
3753    * spin up.
3754    */
3755
3756   if (header->GIOP_version.minor > 1) {
3757     while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
3758       ++(offset);
3759   }
3760
3761   switch(locate_status) {
3762   case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
3763   case OBJECT_FORWARD_PERM:
3764     decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3765     break;
3766   case LOC_SYSTEM_EXCEPTION:
3767     decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3768     break;
3769   case LOC_NEEDS_ADDRESSING_MODE:
3770     addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3771     if(locate_reply_tree) {
3772       proto_tree_add_text (tree, tvb, offset -2, 2,
3773                            "AddressingDisposition: %u", addr_disp);
3774     }
3775     break;
3776   default: /* others have no reply body */
3777     break;
3778   }
3779
3780 }
3781
3782 static void
3783 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
3784                         MessageHeader * header, gboolean stream_is_big_endian)
3785 {
3786   guint32 offset = 0;
3787   guint32 request_id;
3788   proto_tree *fragment_tree = NULL;
3789   proto_item *tf;
3790
3791   if (tree)
3792     {
3793       tf = proto_tree_add_text (tree, tvb, offset,
3794                                 tvb_length (tvb),
3795                                 "General Inter-ORB Fragment");
3796       if (fragment_tree == NULL)
3797         {
3798           fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
3799
3800         }
3801     }
3802
3803   request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3804   if (check_col(pinfo->cinfo, COL_INFO))
3805     {
3806       col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
3807     }
3808   if (fragment_tree )
3809     {
3810       proto_tree_add_text (fragment_tree, tvb, offset-4, 4,
3811                            "Request id: %u", request_id);
3812     }
3813                                    
3814 }
3815
3816
3817 /* Main entry point */
3818
3819 gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
3820   u_int offset = 0;
3821   MessageHeader header;
3822   tvbuff_t *giop_header_tvb;
3823   tvbuff_t *payload_tvb;
3824
3825   proto_tree *clnp_tree = NULL;
3826   proto_item *ti;
3827   u_int message_size;
3828   u_int minor_version;
3829   gboolean stream_is_big_endian;
3830
3831
3832   /* DEBUG */
3833   
3834 #if DEBUG
3835   giop_dump_collection(cd_module_hash);
3836   giop_dump_collection(cd_objkey_hash);
3837   giop_dump_collection(cd_heuristic_users);
3838   giop_dump_collection(cd_complete_reply_hash);
3839   giop_dump_collection(cd_complete_request_list);
3840 #endif
3841
3842   header.exception_id = NULL;
3843
3844   /* check magic number and version */
3845
3846
3847   /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
3848
3849   if (tvb_length_remaining(tvb, 0) < GIOP_HEADER_SIZE)
3850     {
3851       /* Not enough data captured to hold the GIOP header; don't try
3852          to interpret it as GIOP. */
3853       return FALSE;
3854     }
3855
3856   giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
3857   payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
3858   
3859   /*
3860    * because I have added extra elements in MessageHeader struct
3861    * for sub dissectors. -- FS
3862    */
3863
3864   tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
3865
3866   if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
3867     {
3868       /* Not a GIOP message. */
3869
3870       return FALSE;
3871     }
3872
3873   if (check_col (pinfo->cinfo, COL_PROTOCOL))
3874     {
3875       col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
3876     }
3877
3878   if (header.GIOP_version.major != GIOP_MAJOR ||
3879       ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
3880     {
3881       /* Bad version number; should we note that and dissect the rest
3882          as data, or should we return FALSE on the theory that it
3883          might have been some other packet that happened to begin with
3884          "GIOP"?  We shouldn't do *both*, so we return TRUE, for now.
3885          If we should return FALSE, we should do so *without* setting
3886          the "Info" column, *without* setting the "Protocol" column,
3887          and *without* adding anything to the protocol tree. */
3888
3889       if (check_col (pinfo->cinfo, COL_INFO))
3890         {
3891           col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
3892                         header.GIOP_version.major, header.GIOP_version.minor);
3893         }
3894       if (tree)
3895         {
3896           ti = proto_tree_add_item (tree, proto_giop, tvb, 0,
3897                                     tvb_length (tvb), FALSE);
3898           clnp_tree = proto_item_add_subtree (ti, ett_giop);
3899           proto_tree_add_text (clnp_tree, giop_header_tvb, 0,
3900                                tvb_length (giop_header_tvb),
3901                                "Version %u.%u not supported",
3902                                header.GIOP_version.major,
3903                                header.GIOP_version.minor);
3904         }
3905       call_dissector(data_handle,payload_tvb, pinfo, tree);
3906       return TRUE;
3907     }
3908
3909   if (check_col (pinfo->cinfo, COL_INFO)) 
3910   { 
3911       col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3912                     header.GIOP_version.major, header.GIOP_version.minor,
3913                     val_to_str(header.message_type, giop_message_types,
3914                                "Unknown message type (0x%02x)"));
3915   }
3916
3917   stream_is_big_endian = is_big_endian (&header);
3918
3919   if (stream_is_big_endian)
3920     message_size = pntohl (&header.message_size);
3921   else
3922     message_size = pletohl (&header.message_size);
3923
3924   if (tree)
3925     {
3926       ti = proto_tree_add_item (tree, proto_giop, tvb, 0, 12, FALSE);
3927       clnp_tree = proto_item_add_subtree (ti, ett_giop);
3928       proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
3929                            "Magic number: %s", GIOP_MAGIC);
3930       proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
3931                            "Version: %u.%u",
3932                            header.GIOP_version.major,
3933                            header.GIOP_version.minor);
3934       switch (minor_version)
3935         {
3936         case 2:
3937         case 1:
3938           proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3939                                "Flags: 0x%02x (%s %s)",
3940                                header.flags,
3941                                (stream_is_big_endian) ? "big-endian" : "little-endian",
3942                                (header.flags & 0x02) ? " fragment" : "");
3943           break;
3944         case 0:
3945           proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
3946                                "Byte ordering: %s-endian",
3947                                (stream_is_big_endian) ? "big" : "little");
3948           break;
3949         default:
3950           break;
3951         }                       /* minor_version */
3952
3953       proto_tree_add_uint_format (clnp_tree,
3954                                   hf_giop_message_type,
3955                                   giop_header_tvb, 7, 1,
3956                                   header.message_type,
3957                                   "Message type: %s", match_strval(header.message_type, giop_message_types));
3958
3959       proto_tree_add_uint (clnp_tree,
3960                            hf_giop_message_size,
3961                            giop_header_tvb, 8, 4, message_size);
3962
3963     }                           /* tree */
3964
3965 #if 0
3966   if (check_col (pinfo->cinfo, COL_INFO)) 
3967   { 
3968       col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
3969                     header.GIOP_version.major, header.GIOP_version.minor,
3970                     match_strval(header.message_type, giop_message_types));
3971   }
3972 #endif
3973
3974   switch (header.message_type)
3975     {
3976
3977     case Request:
3978       if(header.GIOP_version.minor < 2)
3979       {
3980            dissect_giop_request_1_1 (payload_tvb, pinfo, tree, clnp_tree,
3981                                      &header, stream_is_big_endian);
3982       }
3983       else
3984       {    
3985            dissect_giop_request_1_2 (payload_tvb, pinfo, tree, clnp_tree,
3986                                      &header, stream_is_big_endian);
3987       }
3988       
3989       break;
3990
3991
3992     case Reply:
3993       if(header.GIOP_version.minor < 2)
3994         {
3995            dissect_giop_reply (payload_tvb, pinfo, tree, clnp_tree, &header,
3996                                stream_is_big_endian);
3997         }
3998       else
3999         {
4000            dissect_giop_reply_1_2 (payload_tvb, pinfo, tree, clnp_tree,
4001                                    &header, stream_is_big_endian);
4002         }
4003       break;
4004     case CancelRequest:
4005         dissect_giop_cancel_request(payload_tvb, pinfo, tree, clnp_tree,
4006                                     &header, stream_is_big_endian);
4007         break;
4008     case LocateRequest:
4009         dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
4010                                     stream_is_big_endian);
4011         break;
4012     case LocateReply:
4013         dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
4014                                   stream_is_big_endian);
4015         break;
4016     case Fragment:
4017         dissect_giop_fragment(payload_tvb, pinfo, tree, &header,
4018                               stream_is_big_endian);
4019         break;  
4020     default:
4021       break;
4022
4023     }                           /* switch message_type */
4024
4025
4026   /*
4027    * XXX - we should catch exceptions here, so that we can free
4028    * this if an exception is thrown.
4029    * We'd then have to forward the exception.
4030    */
4031   if (header.exception_id != NULL)
4032     g_free(header.exception_id);
4033
4034   return TRUE;
4035 }
4036
4037 void
4038 proto_register_giop (void)
4039 {
4040   static hf_register_info hf[] = {
4041     { &hf_giop_message_type,
4042      { "Message type", "giop.type",
4043        FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4044     },
4045     
4046     { &hf_giop_message_size,
4047       { "Message size", "giop.len",
4048         FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4049     },
4050
4051     { &hf_giop_repoid,
4052      { "Repository ID", "giop.repoid",
4053        FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4054     },
4055
4056     { &hf_giop_string_length,
4057      { "String Length", "giop.strlen",
4058        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4059     },
4060
4061     { &hf_giop_sequence_length,
4062      { "Sequence Length", "giop.seqlen",
4063        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4064     },
4065
4066     { &hf_giop_profile_id,
4067      { "Profile ID", "giop.profid",
4068        FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
4069     },
4070
4071
4072     { &hf_giop_type_id,
4073      { "IOR::type_id", "giop.typeid",
4074        FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4075     },
4076
4077     { &hf_giop_iiop_v_maj,
4078      { "IIOP Major Version", "giop.iiop_vmaj",
4079        FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4080     }
4081     ,
4082     { &hf_giop_iiop_v_min,
4083      { "IIOP Minor Version", "giop.iiop_vmin",
4084        FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4085     },
4086
4087     { &hf_giop_endianess,
4088      { "Endianess", "giop.endianess",
4089        FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
4090     },
4091
4092     { &hf_giop_IIOP_tag,
4093      { "IIOP Component TAG", "giop.iioptag",
4094        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4095     },
4096
4097     { &hf_giop_IOR_tag,
4098      { "IOR Profile TAG", "giop.iortag",
4099        FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
4100     },
4101
4102     { &hf_giop_TCKind,
4103      { "TypeCode enum", "giop.TCKind",
4104        FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
4105     },
4106
4107     { &hf_giop_typecode_count,
4108      { "TypeCode count", "giop.tccount",
4109        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4110     },
4111
4112     { &hf_giop_typecode_default_used,
4113      { "default_used", "giop.tcdefault_used",
4114        FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4115     },
4116
4117     { &hf_giop_typecode_digits,
4118      { "Digits", "giop.tcdigits",
4119        FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4120     },
4121
4122
4123     { &hf_giop_typecode_length,
4124      { "Length", "giop.tclength",
4125        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4126     },
4127
4128     { &hf_giop_typecode_max_length,
4129      { "Maximum length", "giop.tcmaxlen",
4130        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4131     },
4132
4133     { &hf_giop_typecode_member_name,
4134      { "TypeCode member name", "giop.tcmemname",
4135        FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4136     },
4137
4138     { &hf_giop_typecode_name,
4139      { "TypeCode name", "giop.tcname",
4140        FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4141     },
4142
4143     { &hf_giop_typecode_scale,
4144      { "Scale", "giop.tcscale",
4145        FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4146     },
4147
4148     { &hf_giop_typecode_ValueModifier,
4149      { "ValueModifier", "giop.tcValueModifier",
4150        FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4151     },
4152
4153     { &hf_giop_typecode_Visibility,
4154      { "Visibility", "giop.tcVisibility",
4155        FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4156     },
4157
4158
4159
4160     { &hf_giop_type_boolean,
4161       { "TypeCode boolean data", "giop.tcboolean",
4162         FT_BOOLEAN, BASE_DEC,  NULL, 0x0, "", HFILL }
4163     },
4164
4165     { &hf_giop_type_char,
4166       { "TypeCode char data", "giop.tcchar",
4167         FT_UINT8, BASE_DEC,  NULL, 0x0, "", HFILL }
4168     },
4169
4170     { &hf_giop_type_double,
4171       { "TypeCode double data", "giop.tcdouble",
4172         FT_DOUBLE, BASE_DEC,  NULL, 0x0, "", HFILL }
4173     },
4174
4175     { &hf_giop_type_enum,
4176      { "TypeCode enum data", "giop.tcenumdata",
4177        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4178     },
4179
4180     /*
4181      * float as double ?? -- FIX
4182      */
4183
4184     { &hf_giop_type_float,
4185       { "TypeCode float data", "giop.tcfloat",
4186         FT_DOUBLE, BASE_DEC,  NULL, 0x0, "", HFILL }
4187     },
4188
4189     { &hf_giop_type_long,
4190      { "TypeCode long data", "giop.tclongdata",
4191        FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
4192     },
4193
4194     { &hf_giop_type_octet,
4195       { "TypeCode octet data", "giop.tcoctet",
4196         FT_UINT8, BASE_DEC,  NULL, 0x0, "", HFILL }
4197     },
4198
4199     { &hf_giop_type_short,
4200      { "TypeCode short data", "giop.tcshortdata",
4201        FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
4202     },
4203
4204     { &hf_giop_type_string,
4205       { "TypeCode string data", "giop.tcstring",
4206         FT_STRING, BASE_DEC,  NULL, 0x0, "", HFILL }
4207     },
4208
4209     { &hf_giop_type_ulong,
4210      { "TypeCode ulong data", "giop.tculongdata",
4211        FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
4212     },
4213
4214     { &hf_giop_type_ushort,
4215      { "TypeCode ushort data", "giop.tcushortdata",
4216        FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4217     },
4218
4219     /*
4220      * IIOP Module - Chapter 15.10.2
4221      */
4222
4223     { &hf_giop_iiop_host,
4224      { "IIOP::Profile_host", "giop.iiop.host",
4225        FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
4226     }
4227     ,
4228
4229     { &hf_giop_iiop_port,
4230      { "IIOP::Profile_port", "giop.iiop.port",
4231        FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
4232     }
4233     ,
4234
4235     /*
4236      * IIOP ServiceContext
4237      */
4238
4239     { &hf_giop_iop_vscid,
4240      { "VSCID", "giop.iiop.vscid",
4241        FT_UINT32, BASE_HEX, NULL, 0xfffff000, "", HFILL }
4242     }
4243     ,
4244
4245     { &hf_giop_iop_scid,
4246      { "SCID", "giop.iiop.scid",
4247        FT_UINT32, BASE_HEX, NULL, 0x00000fff, "", HFILL }
4248     }
4249     ,
4250
4251
4252   };
4253
4254   static gint *ett[] = {
4255     &ett_giop,
4256     &ett_giop_reply,
4257     &ett_giop_request,
4258     &ett_giop_cancel_request,
4259     &ett_giop_locate_request,
4260     &ett_giop_locate_reply,
4261     &ett_giop_fragment,
4262     &ett_giop_scl,
4263     &ett_giop_ior
4264
4265   };
4266   proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
4267                                        "giop");
4268   proto_register_field_array (proto_giop, hf, array_length (hf));
4269   proto_register_subtree_array (ett, array_length (ett));
4270
4271
4272   /* register init routine */
4273
4274   register_init_routine( &giop_init); /* any init stuff */
4275
4276   /*
4277    * Init the giop user module hash tables here, as giop users
4278    * will populate it via register_giop_user_module BEFORE my
4279    * own giop_init() is called.
4280    */
4281
4282   giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
4283   
4284   giop_module_keys = g_mem_chunk_new("giop_module_keys",
4285                                      sizeof(struct giop_module_key),
4286                                      giop_module_init_count * sizeof(struct giop_module_key), 
4287                                      G_ALLOC_AND_FREE);
4288   
4289   giop_module_vals = g_mem_chunk_new("giop_module_vals", 
4290                                      sizeof(struct giop_module_val),
4291                                      giop_module_init_count * sizeof(struct giop_module_val), 
4292                                      G_ALLOC_AND_FREE);
4293   
4294 }
4295
4296
4297
4298 void proto_reg_handoff_giop (void) {
4299   data_handle = find_dissector("data");
4300   heur_dissector_add("tcp", dissect_giop, proto_giop);
4301 }
4302
4303
4304
4305
4306 /*
4307  * Decode IOR
4308  *
4309  * Ref Corba v2.4.2 Chapter 13
4310  *
4311  */
4312
4313 /*
4314
4315 module IOP{ 
4316
4317     typedef unsigned long ProfileId;
4318
4319     const ProfileId TAG_INTERNET_IOP = 0;
4320     const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
4321
4322     struct TaggedProfile {
4323       ProfileId tag;
4324       sequence <octet> profile_data;
4325     };
4326
4327     struct IOR {
4328       string type_id;
4329       sequence <TaggedProfile> profiles;
4330     };
4331
4332     typedef unsigned long ComponentId;
4333
4334     struct TaggedComponent {
4335       ComponentId tag;
4336       sequence <octet> component_data;
4337     };
4338
4339     typedef sequence <TaggedComponent> MultipleComponentProfile;
4340
4341 };
4342
4343 */
4344
4345 void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4346                 guint32 boundary, gboolean stream_is_big_endian) {
4347
4348
4349   guint32 seqlen_p;             /* sequence length of profiles */
4350   guint32 u_octet4;
4351
4352   proto_tree *tree = NULL;      /* IOR tree */
4353   proto_item *tf;
4354
4355   gchar *repobuf;               /* for repository ID */
4356
4357   guint32 i;
4358
4359   /* create a subtree */
4360
4361   if (ptree) {
4362     tf = proto_tree_add_text (ptree, tvb, *offset, tvb_length (tvb), "IOR");
4363     tree = proto_item_add_subtree (tf, ett_giop_ior);
4364   }
4365
4366
4367   /* Get type_id  == Repository ID */
4368
4369   u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
4370
4371   if (tree) {    
4372     proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4373                         *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4374     if (u_octet4 > 0) {
4375       proto_tree_add_string(tree,hf_giop_type_id,tvb,
4376                             *offset-u_octet4,u_octet4,repobuf);
4377     }
4378   }
4379
4380   /*
4381    * Register a cleanup function in case on of our tvbuff accesses
4382    * throws an exception. We need to clean up repobuf.
4383    * We can't free it yet, as we must wait until we have the object
4384    * key, as we have to add both to the hash table.
4385    */
4386   CLEANUP_PUSH(g_free, repobuf);
4387
4388   /* Now get a sequence of profiles */
4389   /* Get sequence length (number of elements) */
4390   
4391   seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4392   if (tree) {
4393     proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4394                         *offset-sizeof(seqlen_p),4,seqlen_p);
4395   }
4396   
4397
4398   /* fetch all TaggedProfiles in this sequence */
4399   
4400   for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
4401     decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
4402   }
4403
4404   /*
4405    * We're done with repobuf, so we can call the cleanup handler to free
4406    * it, and then pop the cleanup handler.
4407    */
4408   CLEANUP_CALL_AND_POP;
4409
4410 }
4411
4412 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4413                                  guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
4414
4415   guint32 seqlen_pd;            /* sequence length of profile data */
4416
4417   guint32 pidtag;               /* profile ID TAG */
4418
4419   gchar *profile_data;          /* profile_data pointer */
4420   gchar *p_profile_data;        /* printable profile_data pointer */
4421
4422   guint32 new_boundary;         /* for encapsulations encountered */
4423   gboolean new_big_endianess;   /* for encapsulations encountered */
4424
4425   /* Get ProfileId tag */
4426
4427   pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4428
4429   if (tree) {
4430     proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
4431                         *offset-sizeof(pidtag),4,pidtag);
4432   }
4433
4434   /* get sequence length, new endianness and boundary for encapsulation */
4435   
4436   seqlen_pd = get_CDR_encap_info(tvb, tree, offset, 
4437                                  stream_is_big_endian, boundary,
4438                                  &new_big_endianess, &new_boundary);
4439
4440   /* return if zero length sequence */
4441
4442   if(seqlen_pd == 0)
4443     return;
4444
4445     
4446   /*
4447    * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then 
4448    * decode it, otherwise just dump the octet sequence 
4449    *
4450    * also, store IOR in our objectkey hash
4451    *
4452    * TODO - handle other TAGS
4453    */
4454
4455   switch(pidtag) {
4456   case IOP_TAG_INTERNET_IOP:
4457     
4458     decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
4459     break;
4460
4461   default:
4462     
4463     /* fetch all octets in this sequence , but skip endianess */
4464       
4465     get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
4466       
4467     /* Make a printable string */
4468       
4469     p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
4470       
4471     if(tree) {
4472       proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
4473                            "Profile Data: %s", p_profile_data);
4474     }
4475       
4476     g_free(p_profile_data);
4477
4478     g_free(profile_data);
4479
4480     break;
4481       
4482   }
4483
4484 }
4485
4486
4487
4488 /*
4489  * Decode IIOP IOR Profile
4490  * Ref Chap 15.7.2 in Corba Spec
4491  */
4492
4493
4494 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4495                                     guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
4496                                     gboolean store_flag) {
4497
4498   guint32 i;                    /* loop index */
4499
4500   guint8 v_major,v_minor;       /* IIOP sersion */
4501   gchar *buf;
4502   guint32 u_octet4;             /* u long */
4503   guint16 u_octet2;             /* u short */
4504   guint32 seqlen;               /* generic sequence length */
4505   guint32 seqlen1;              /* generic sequence length */
4506   gchar *objkey;                /* object key pointer */
4507   gchar *p_chars;               /* printable characters pointer */
4508
4509   
4510   /* Get major/minor version */
4511
4512   v_major = get_CDR_octet(tvb,offset);
4513   v_minor = get_CDR_octet(tvb,offset);
4514
4515
4516   if (tree) {    
4517     proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
4518                         *offset-sizeof(v_minor)-sizeof(v_major),1,v_major  );
4519     proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
4520                         *offset-sizeof(v_minor),1,v_minor  );
4521   }
4522
4523
4524   /* host */
4525   
4526   u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
4527    
4528   if (tree) {    
4529     proto_tree_add_uint(tree,hf_giop_string_length,tvb,
4530                         *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
4531     if (u_octet4 > 0) {
4532       proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
4533                             *offset-u_octet4,u_octet4,buf);
4534     }
4535   }
4536   
4537   g_free(buf);          /* dont forget */
4538     
4539   /* Port */
4540
4541   u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
4542
4543   if (tree) {    
4544     proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
4545                         *offset-sizeof(u_octet2),2,u_octet2);
4546   }
4547
4548
4549   /* Object Key - sequence<octet> object_key */
4550
4551   seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4552
4553   if (tree) {
4554     proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4555                         *offset-sizeof(seqlen),4,seqlen);
4556   }
4557
4558   if (seqlen > 0) {
4559     /* fetch all octets in this sequence */  
4560     get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
4561
4562     /*
4563      * Now we may have the Repository ID from earlier, as well
4564      * as the object key sequence and lengh. So lets store them in
4565      * our objectkey hash and free buffers.
4566      *
4567      * But only insert if user is not clicking and repo id not NULL.
4568      *
4569      */
4570
4571     if (repo_id_buf) {
4572       if (pinfo) {
4573         if(!pinfo->fd->flags.visited)
4574           insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res); 
4575       }
4576       else {
4577  
4578         /*
4579          * No pinfo, but store anyway if flag set. eg: IOR read from file
4580          */
4581
4582         if (store_flag)
4583           insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file); 
4584       }
4585     }
4586
4587     /* Make a printable string */
4588   
4589     p_chars = make_printable_string( objkey, seqlen );
4590   
4591     if(tree) {
4592       proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
4593                          "Object Key: %s", p_chars);
4594     }
4595
4596     g_free(p_chars);
4597     g_free(objkey);  
4598   }
4599   
4600   /*
4601    * Now see if if its v1.1 or 1.2, as they can contain
4602    * extra sequence of IOP::TaggedComponents
4603    *
4604    */
4605   
4606   switch(v_minor) {
4607   case 0:
4608
4609     /* nothing extra */
4610     break;
4611
4612   case 1:
4613   case 2:
4614
4615     /* sequence of IOP::TaggedComponents */
4616     /* Ref Chap 13 in Corba Spec */
4617
4618     /* get sequence length */
4619     seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4620
4621     if (tree) {
4622       proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4623                           *offset-sizeof(seqlen),4,seqlen);
4624     }
4625
4626     for (i=0; i< seqlen; i++) {
4627       /* get tag */
4628       u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4629       if (tree) {
4630         proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
4631                             *offset-sizeof(u_octet4),4,u_octet4);
4632       }
4633
4634       /* get component_data */
4635       seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
4636       if (tree) {
4637         proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4638                             *offset-sizeof(seqlen1),4,seqlen1);
4639       }
4640
4641       if (seqlen1 > 0) {
4642         get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
4643
4644         if (tree) {
4645           /* Make a printable string of data */
4646   
4647           p_chars = make_printable_string(buf, seqlen1);
4648   
4649           proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
4650                                "component_data: %s", p_chars);
4651   
4652           g_free(p_chars);
4653         }
4654
4655         g_free(buf);
4656       }
4657
4658     }
4659
4660
4661     break;
4662
4663   default:
4664     g_warning("giop:Invalid v_minor value = %u ", v_minor);
4665     break;
4666   }
4667   
4668 }
4669
4670
4671 /* 
4672  * Service Contexts Begin
4673  *
4674  */
4675
4676
4677
4678
4679
4680 void dissect_SID_BI_DIR_IIOP(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
4681                                MessageHeader *header, gchar *operation, guint32 boundary) {
4682
4683   return;
4684
4685 };
4686
4687
4688
4689
4690 /*
4691  * Service Contexts End
4692  *
4693  */
4694
4695
4696
4697
4698 /*
4699  * Corba , chp 13.7
4700  *
4701  *
4702  *
4703  *      typedef unsigned long ServiceID;
4704  *
4705  *      struct ServiceContext {
4706  *              ServiceID context_id;
4707  *              sequence <octet> context_data;
4708  *      };
4709  *      typedef sequence <ServiceContext> ServiceContextList;
4710  *
4711  *
4712  * Note: Spec says context_data is an encapsulation.
4713  *
4714  *
4715  */
4716
4717
4718
4719 void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
4720                                gboolean stream_is_be, guint32 boundary) {
4721
4722   guint32 seqlen;               /* sequence length  */
4723   guint32 seqlen_cd;            /* sequence length, context_data  */
4724
4725   proto_tree *tree = NULL;      /* ServiceContext tree */
4726   proto_item *tf;
4727
4728   guint32 context_id;
4729   gchar *context_data;
4730   gchar *p_context_data;
4731
4732   guint32 i;
4733   guint32 vscid;                /* Vendor Service context id */
4734   guint32 scid;
4735
4736   /* create a subtree */
4737
4738   if (ptree) {
4739     tf = proto_tree_add_text (ptree, tvb, *offset, tvb_length (tvb), "ServiceContextList");
4740     tree = proto_item_add_subtree (tf, ett_giop_scl);
4741   }
4742
4743   /* Get sequence length (number of elements) */
4744   
4745   seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4746   if (tree) {
4747     proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
4748                         *offset-sizeof(seqlen),4,seqlen);
4749   }
4750
4751   /* return if zero length sequence */
4752
4753   if(seqlen == 0)
4754     return;
4755      
4756   /* Loop for all ServiceContext's */
4757
4758   for (i=0; i<seqlen; i++) {
4759
4760     context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
4761     if (tree) {
4762       proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
4763                           *offset-sizeof(context_id),4,context_id);
4764
4765       proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
4766                           *offset-sizeof(context_id),4,context_id);
4767
4768     }
4769  
4770     vscid = context_id && 0xfffff000; /* vendor info, top 20 bits */
4771     scid = context_id  && 0x00000fff; /* standard service info, lower 12 bits */
4772
4773
4774 #if CONTEXT_DATA_IS_ENCAPSULATED
4775
4776     /* get sequence length, new endianness and boundary for encapsulation */
4777   
4778     seqlen_cd = get_CDR_encap_info(tvb, tree, offset, 
4779                                stream_is_be, boundary,
4780                                &new_big_endianess, &new_boundary);
4781
4782
4783 #else
4784    /* get sequence length, and NO  encapsulation */
4785
4786     seqlen_cd = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
4787
4788 #endif
4789
4790     /* return if zero length sequence */
4791
4792     if(seqlen_cd == 0)
4793       return;
4794     
4795     /*
4796      * Now decode sequence according to vendor ServiceId, but I dont
4797      * have that yet, so just dump it as data.
4798      */    
4799
4800     /* fetch all octets in this sequence */
4801   
4802     get_CDR_octet_seq(tvb, &context_data, offset, seqlen_cd);
4803
4804     /* Make a printable string */
4805   
4806     p_context_data = make_printable_string( context_data, seqlen_cd );
4807   
4808     if(tree) {
4809       proto_tree_add_text (tree, tvb, *offset - seqlen_cd , seqlen_cd,
4810                            "context_data: %s", p_context_data);
4811     }
4812
4813     g_free(context_data);
4814     g_free(p_context_data);
4815
4816   } /* seqlen  */
4817
4818
4819   return;                       /* for now, fix later */
4820     
4821
4822 }
4823
4824 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
4825  */
4826
4827 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
4828                                              gboolean stream_is_big_endian,
4829                                              guint32 boundary) {
4830
4831   guint32 length;            /* string length */
4832   guint32 minor_code_value;
4833   guint32 completion_status;
4834
4835   gchar *buf;                /* pointer to string buffer */ 
4836
4837   length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
4838
4839   if (tree) {
4840     proto_tree_add_text(tree, tvb, *offset-4, 4,
4841                         "Exception length: %u", length);
4842     if (length > 0) {
4843       proto_tree_add_text(tree, tvb, *offset - length, length,
4844                           "Exception id: %s", buf );
4845     }
4846   }
4847   g_free(buf);
4848
4849   minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4850   completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
4851         
4852   if (tree) {
4853     proto_tree_add_text(tree, tvb, *offset-8, 4,
4854                         "Minor code value: %u", minor_code_value);
4855     proto_tree_add_text(tree, tvb, *offset-4, 4,
4856                         "Completion Status: %u", completion_status);
4857   }
4858 }
4859
4860
4861 /*
4862  * Helper functions for dissecting TypeCodes 
4863  *
4864  * These functions decode the complex parameter lists
4865  * of TypeCodes as defined in the CORBA spec chapter 15.
4866  */
4867
4868 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
4869                                      gboolean stream_is_big_endian, guint32 boundary,
4870                                      MessageHeader * header) {
4871
4872   guint32  new_boundary;             /* new boundary for encapsulation */
4873   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4874
4875   guint32 seqlen;   /* sequence length */
4876
4877   /* get sequence length, new endianness and boundary for encapsulation */
4878   seqlen = get_CDR_encap_info(tvb, tree, offset, 
4879                                    stream_is_big_endian, boundary,
4880                                    &new_stream_is_big_endian, &new_boundary);
4881
4882   /* get repository ID */
4883   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4884                                 hf_giop_repoid);
4885
4886   /* get name */
4887   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4888                                 hf_giop_typecode_name);
4889
4890 }
4891
4892
4893 static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
4894                                      gboolean stream_is_big_endian, guint32 boundary,
4895                                      MessageHeader * header ) {
4896
4897   guint32  new_boundary;             /* new boundary for encapsulation */
4898   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4899
4900   guint32 count;    /* parameter count (of tuples)  */
4901   guint32 seqlen;   /* sequence length */
4902   guint32 i;        /* loop index */
4903
4904   /* get sequence lengt,h new endianness and boundary for encapsulation */
4905   seqlen = get_CDR_encap_info(tvb, tree, offset, 
4906                                    stream_is_big_endian, boundary,
4907                                    &new_stream_is_big_endian, &new_boundary);
4908
4909   /* get repository ID */
4910   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4911                                 hf_giop_repoid);
4912
4913   /* get name */
4914   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4915                                 hf_giop_typecode_name);
4916
4917   /* get count of tuples */
4918   count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4919   if (tree) {
4920     proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4921                         *offset-sizeof(count),4,count);
4922   }
4923
4924   /* get all tuples */
4925   for (i=0; i< count; i++) {
4926     /* get member name */
4927     dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4928                                   hf_giop_typecode_member_name);
4929
4930     /* get member type */
4931     get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4932   }
4933
4934 }
4935
4936
4937 static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
4938                                     gboolean stream_is_big_endian, guint32 boundary,
4939                                     MessageHeader * header) {
4940
4941   guint32  new_boundary;             /* new boundary for encapsulation */
4942   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
4943
4944   guint32  TCKind;    /* TypeCode */
4945   gint32   s_octet4;  /* signed int32 */
4946
4947   guint32 count;    /* parameter count (of tuples)  */
4948   guint32 seqlen;   /* sequence length */
4949   guint32 i;        /* loop index */
4950
4951   /* get sequence legnth, new endianness and boundary for encapsulation */
4952   seqlen = get_CDR_encap_info(tvb, tree, offset, 
4953                                    stream_is_big_endian, boundary,
4954                                    &new_stream_is_big_endian, &new_boundary);
4955
4956   /* get repository ID */
4957   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4958                                 hf_giop_repoid);
4959
4960   /* get name */
4961   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4962                                 hf_giop_typecode_name);
4963
4964   /* get discriminant type */
4965   TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4966
4967   /* get default used */
4968   s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
4969   if (tree) {
4970     proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
4971                         *offset-sizeof(s_octet4),4,s_octet4);
4972   }
4973   /* get count of tuples */
4974   count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
4975   if (tree) {
4976     proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
4977                         *offset-sizeof(count),4,count);
4978   }
4979
4980   /* get all tuples */
4981   for (i=0; i< count; i++) {
4982     /* get label value, based on TCKind above  */
4983     dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
4984
4985     /* get member name */
4986     dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
4987                                   hf_giop_typecode_member_name);
4988
4989     /* get member type */
4990     get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
4991   }
4992
4993 }
4994
4995
4996 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
4997                                    gboolean stream_is_big_endian, guint32 boundary,
4998                                    MessageHeader * header) {
4999
5000   guint32  new_boundary;             /* new boundary for encapsulation */
5001   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5002
5003   guint32 count;    /* parameter count (of tuples)  */
5004   guint32 seqlen;   /* sequence length */
5005   guint32 i;        /* loop index */
5006
5007   /* get sequence length, new endianness and boundary for encapsulation */
5008   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5009                                    stream_is_big_endian, boundary,
5010                                    &new_stream_is_big_endian, &new_boundary);
5011
5012   /* get repository ID */
5013   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5014                                 hf_giop_repoid);
5015
5016   /* get name */
5017   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5018                                 hf_giop_typecode_name);
5019
5020   /* get count of tuples */
5021   count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5022   if (tree) {
5023     proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5024                         *offset-sizeof(count),4,count);
5025   }
5026
5027   /* get all tuples */
5028   for (i=0; i< count; i++) {
5029     /* get member name */
5030     dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5031                                   hf_giop_typecode_member_name);
5032   }
5033
5034 }
5035
5036
5037 static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5038                                        gboolean stream_is_big_endian, guint32 boundary,
5039                                        MessageHeader * header) {
5040
5041   guint32  new_boundary;             /* new boundary for encapsulation */
5042   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5043
5044   guint32 u_octet4; /* unsigned int32 */
5045
5046   guint32 seqlen;   /* sequence length */
5047
5048   /* get sequence length, new endianness and boundary for encapsulation */
5049   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5050                                    stream_is_big_endian, boundary,
5051                                    &new_stream_is_big_endian, &new_boundary);
5052
5053   /* get element type */
5054   get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5055
5056   /* get max length */
5057   u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5058   if (tree) {
5059     proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
5060                         *offset-sizeof(u_octet4),4,u_octet4);
5061   }
5062 }
5063
5064
5065 static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5066                                     gboolean stream_is_big_endian, guint32 boundary,
5067                                     MessageHeader * header) {
5068
5069   guint32  new_boundary;             /* new boundary for encapsulation */
5070   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5071
5072   guint32 u_octet4; /* unsigned int32 */
5073
5074   guint32 seqlen;   /* sequence length */
5075
5076   /* get sequence length, new endianness and boundary for encapsulation */
5077   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5078                                    stream_is_big_endian, boundary,
5079                                    &new_stream_is_big_endian, &new_boundary);
5080
5081   /* get element type */
5082   get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5083
5084   /* get length */
5085   u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5086   if (tree) {
5087     proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
5088                         *offset-sizeof(u_octet4),4,u_octet4);
5089   }
5090 }
5091
5092
5093 static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5094                                     gboolean stream_is_big_endian, guint32 boundary,
5095                                     MessageHeader * header) {
5096
5097   guint32  new_boundary;             /* new boundary for encapsulation */
5098   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5099
5100   guint32 seqlen;   /* sequence length */
5101
5102   /* get sequence legnth, new endianness and boundary for encapsulation */
5103   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5104                                    stream_is_big_endian, boundary,
5105                                    &new_stream_is_big_endian, &new_boundary);
5106
5107   /* get repository ID */
5108   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5109                                 hf_giop_repoid);
5110
5111   /* get name */
5112   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5113                                 hf_giop_typecode_name);
5114
5115   /* get ??? (noname) TypeCode */
5116   get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5117
5118 }
5119
5120
5121 static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5122                                      gboolean stream_is_big_endian, guint32 boundary,
5123                                      MessageHeader * header) {
5124
5125   guint32  new_boundary;             /* new boundary for encapsulation */
5126   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5127
5128   guint32 count;    /* parameter count (of tuples)  */
5129   guint32 seqlen;   /* sequence length */
5130   guint32 i;        /* loop index */
5131
5132   /* get sequence length, new endianness and boundary for encapsulation */
5133   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5134                                    stream_is_big_endian, boundary,
5135                                    &new_stream_is_big_endian, &new_boundary);
5136
5137   /* get repository ID */
5138   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5139                                 hf_giop_repoid);
5140
5141   /* get name */
5142   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5143                                 hf_giop_typecode_name);
5144
5145   /* get count of tuples */
5146   count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5147   if (tree) {
5148     proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5149                         *offset-sizeof(count),4,count);
5150   }
5151
5152   /* get all tuples */
5153   for (i=0; i< count; i++) {
5154     /* get member name */
5155     dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5156                                   hf_giop_typecode_member_name);
5157
5158     /* get member type */
5159     get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5160   }
5161
5162 }
5163
5164
5165 static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5166                                     gboolean stream_is_big_endian, guint32 boundary,
5167                                     MessageHeader * header) {
5168
5169   guint32  new_boundary;             /* new boundary for encapsulation */
5170   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5171
5172   gint16  s_octet2; /* signed int16 */
5173
5174   guint32 count;    /* parameter count (of tuples)  */
5175   guint32 seqlen;   /* sequence length */
5176   guint32 i;        /* loop index */
5177
5178   /* get sequence length, new endianness and boundary for encapsulation */
5179   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5180                                    stream_is_big_endian, boundary,
5181                                    &new_stream_is_big_endian, &new_boundary);
5182
5183   /* get repository ID */
5184   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5185                                 hf_giop_repoid);
5186
5187   /* get name */
5188   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5189                                 hf_giop_typecode_name);
5190
5191   /* get ValueModifier */
5192   s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5193   if (tree) {
5194     proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
5195                        *offset-sizeof(s_octet2),2,s_octet2);
5196   }
5197
5198   /* get conrete base */
5199   get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5200
5201   /* get count of tuples */
5202   count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
5203   if (tree) {
5204     proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
5205                         *offset-sizeof(count),4,count);
5206   }
5207
5208   /* get all tuples */
5209   for (i=0; i< count; i++) {
5210     /* get member name */
5211     dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5212                                   hf_giop_typecode_member_name);
5213
5214     /* get member type */
5215     get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5216
5217     /* get Visibility */
5218     s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5219     if (tree) {
5220       proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
5221                           *offset-sizeof(s_octet2),2,s_octet2);
5222     }
5223   }
5224
5225 }
5226
5227
5228 static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5229                                         gboolean stream_is_big_endian, guint32 boundary,
5230                                         MessageHeader * header) {
5231
5232   guint32  new_boundary;             /* new boundary for encapsulation */
5233   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5234
5235   guint32 seqlen;   /* sequence length */
5236
5237   /* get sequence length, new endianness and boundary for encapsulation */
5238   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5239                                    stream_is_big_endian, boundary,
5240                                    &new_stream_is_big_endian, &new_boundary);
5241
5242   /* get repository ID */
5243   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5244                                 hf_giop_repoid);
5245
5246   /* get name */
5247   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5248                                 hf_giop_typecode_name);
5249
5250   /* get ??? (noname) TypeCode */
5251   get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
5252 }
5253
5254
5255 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5256                                      gboolean stream_is_big_endian, guint32 boundary,
5257                                      MessageHeader * header) {
5258
5259   guint32  new_boundary;             /* new boundary for encapsulation */
5260   gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
5261
5262   guint32 seqlen;   /* sequence length */
5263
5264   /* get sequence length, new endianness and boundary for encapsulation */
5265   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5266                                    stream_is_big_endian, boundary,
5267                                    &new_stream_is_big_endian, &new_boundary);
5268
5269   /* get repository ID */
5270   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5271                                 hf_giop_repoid);
5272
5273   /* get name */
5274   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5275                                 hf_giop_typecode_name);
5276
5277 }
5278
5279
5280 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5281                                                  gboolean stream_is_big_endian, guint32 boundary,
5282                                                  MessageHeader * header) {
5283
5284   guint32  new_boundary;              /* new boundary for encapsulation */
5285   gboolean new_stream_is_big_endian;  /* new endianness for encapsulation */
5286
5287   guint32 seqlen;   /* sequence length */
5288
5289   /* get sequence length, new endianness and boundary for encapsulation */
5290   seqlen = get_CDR_encap_info(tvb, tree, offset, 
5291                                    stream_is_big_endian, boundary,
5292                                    &new_stream_is_big_endian, &new_boundary);
5293
5294   /* get repository ID */
5295   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5296                                 hf_giop_repoid);
5297
5298   /* get name */
5299   dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
5300                                 hf_giop_typecode_name);
5301
5302 }
5303
5304 /* Typecode parameter lists are encoded as encapsulations and
5305  * this function gets the encapsulation information; see
5306  * CORBA spec chapter 15 
5307  *
5308  *
5309  * Renamed to get_CDR_encap_info() for any encapsulation 
5310  * we come across, useful helper function 
5311  *
5312  * Also, should return immediately if seqlen == 0.
5313  * ie: Forget about trying to grab endianess for
5314  *     zero length sequence.
5315  *
5316  * Caller must always check seqlen == 0, and not assume its value
5317  *
5318  *
5319  * Note: there seemed to be considerable confusion in corba
5320  * circles as to the correct interpretation of encapsulations,
5321  * and zero length sequences etc, but this is our best bet at the 
5322  * moment.
5323  *
5324  * -- FS
5325  *
5326  */
5327
5328 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5329                        gboolean old_stream_is_big_endian, guint32 old_boundary,
5330                        gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
5331  
5332   guint32 seqlen;   /* sequence length */
5333   guint8  giop_endianess;
5334
5335   /* Get sequence length of parameter list */
5336   seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
5337   if (tree) {
5338     proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5339                         *offset-sizeof(seqlen),4,seqlen);
5340   }
5341
5342   
5343
5344   /*
5345    * seqlen == 0, implies no endianess and no data
5346    * so just return. Populate new_boundary_ptr and
5347    * new_stream_is_big_endian_ptr with current (old)
5348    * values, just to keep everyone happy. -- FS
5349    *
5350    */
5351
5352   if (seqlen == 0) {
5353
5354     *new_boundary_ptr = old_boundary;
5355     *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
5356
5357     return seqlen;
5358
5359   }
5360
5361   /*  Start of encapsulation of parameter list */
5362   *new_boundary_ptr = *offset;  /* remember  */
5363   giop_endianess =  get_CDR_octet(tvb,offset);
5364
5365   *new_stream_is_big_endian_ptr = ! giop_endianess;
5366
5367   /*
5368    * Glib: typedef gint   gboolean;
5369    * ie: It is not a guint8, so cannot use sizeof to correctly
5370    * highlight octet.
5371    */
5372
5373
5374   if (tree) {
5375     proto_tree_add_uint(tree,hf_giop_endianess,tvb,
5376                         *offset-1,1,giop_endianess);
5377   }
5378
5379
5380   return seqlen;
5381
5382
5383 }
5384
5385 /* 
5386  * gets a TypeCode complex string parameter and
5387  * displays it in the relevant tree.
5388  */
5389
5390 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5391                                           gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
5392
5393   guint32 u_octet4;  /* unsigned int32 */
5394   gchar *buf;        /* ptr to string buffer */
5395
5396   /* get string */
5397   u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
5398    
5399   if (tree) {    
5400     proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5401                         *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5402     if (u_octet4 > 0) {
5403       proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
5404     }
5405   }
5406   
5407   g_free(buf);          /* dont forget */
5408
5409 }
5410
5411 /*
5412  * For a given data type, given by a TypeCode gets the associated data
5413  * and displays it in the relevant tree.
5414  */
5415
5416 static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset, 
5417                                       gboolean stream_is_big_endian, guint32 boundary,
5418                                       MessageHeader * header, guint32 data_type ) {
5419
5420   gboolean my_boolean; /* boolean */
5421
5422   gint8  s_octet1;   /* signed int8 */
5423   guint8 u_octet1;   /* unsigned int8 */
5424
5425   gint16  s_octet2;  /* signed int16 */
5426   guint16 u_octet2;  /* unsigned int16 */
5427
5428   gint32  s_octet4;  /* signed int32 */
5429   guint32 u_octet4;  /* unsigned int32 */
5430
5431   gdouble my_double; /* double */
5432   gfloat  my_float;  /* float */
5433
5434   gchar *buf = NULL;            /* ptr to string buffer */
5435
5436   /* Grab the data according to data type */
5437
5438   switch (data_type) {
5439   case tk_null:
5440     /* nothing to decode */
5441     break;
5442   case tk_void:
5443     /* nothing to decode */
5444     break;
5445   case tk_short:
5446     s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
5447     if (tree) {
5448       proto_tree_add_int(tree,hf_giop_type_short,tvb,
5449                          *offset-sizeof(s_octet2),2,s_octet2);
5450     }
5451     break;
5452   case tk_long:
5453     s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
5454     if (tree) {
5455       proto_tree_add_int(tree,hf_giop_type_long,tvb,
5456                          *offset-sizeof(s_octet4),4,s_octet4);
5457     }
5458     break;
5459   case tk_ushort:
5460     u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5461     if (tree) {
5462       proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
5463                           *offset-sizeof(u_octet2),2,u_octet2);
5464     }
5465     break;
5466   case tk_ulong:
5467     u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5468     if (tree) {
5469       proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
5470                          *offset-sizeof(u_octet4),4,u_octet4);
5471     }
5472     break;
5473   case tk_float:
5474     my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
5475     if (tree) {
5476       proto_tree_add_double(tree,hf_giop_type_float,tvb,
5477                             *offset-sizeof(my_float),4,my_float);
5478     }
5479     break;
5480   case tk_double:
5481     my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
5482     if (tree) {
5483       proto_tree_add_double(tree,hf_giop_type_double,tvb,
5484                             *offset-sizeof(my_double),8,my_double);
5485     }
5486     break;
5487   case tk_boolean:
5488     my_boolean = get_CDR_boolean(tvb,offset);
5489     if (tree) {
5490       proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
5491                              *offset-1,1,my_boolean);
5492     }
5493     break;
5494   case tk_char:
5495     u_octet1 = get_CDR_char(tvb,offset);
5496     if (tree) {
5497       proto_tree_add_uint(tree,hf_giop_type_char,tvb,
5498                           *offset-sizeof(u_octet1),1,u_octet1);
5499     }
5500     break;
5501   case tk_octet:
5502     u_octet1 = get_CDR_octet(tvb,offset);
5503     if (tree) {
5504       proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
5505                           *offset-sizeof(u_octet1),1,u_octet1);
5506     }
5507     break;
5508   case tk_any:
5509     get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
5510     break;
5511   case tk_TypeCode:
5512     get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
5513     break;
5514   case tk_Principal:
5515     break;
5516   case tk_objref:
5517     break;
5518   case tk_struct:
5519     break;
5520   case tk_union:
5521     break;
5522   case tk_enum:
5523     u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
5524     if (tree) {
5525       proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
5526                           *offset-sizeof(u_octet4),4,u_octet4);
5527     }
5528     break;
5529   case tk_string:
5530     u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5531     if (tree) {
5532       proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5533                           *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5534       if (u_octet4 > 0) {
5535         proto_tree_add_string(tree,hf_giop_type_string,tvb,
5536                               *offset-u_octet4,u_octet4,buf);
5537       }
5538     }
5539     
5540     g_free(buf);                /* dont forget */
5541     break;
5542   case tk_sequence:
5543     break;
5544   case tk_array:
5545     break;
5546   case tk_alias:
5547     break;
5548   case tk_except:
5549     break;
5550   case tk_longlong:
5551     break;
5552   case tk_ulonglong:
5553     break;
5554   case tk_longdouble:
5555     break;
5556   case tk_wchar:
5557     s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
5558     if (tree) {
5559       /*
5560        * XXX - can any of these throw an exception?
5561        * If so, we need to catch the exception and free "buf".
5562        */
5563       if (s_octet1 < 0) { /* no size to add to tree */
5564         proto_tree_add_string(tree,hf_giop_type_string,tvb,
5565                               *offset+s_octet1,(-s_octet1),buf);
5566       } else {
5567         proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5568                             *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
5569         proto_tree_add_string(tree,hf_giop_type_string,tvb,
5570                               *offset-s_octet1,s_octet1,buf);
5571       }
5572     }
5573
5574     g_free(buf);              /* dont forget */
5575     break;
5576   case tk_wstring:
5577     u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
5578     if (tree) {
5579       /*
5580        * XXX - can any of these throw an exception?
5581        * If so, we need to catch the exception and free "buf".
5582        */
5583        proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5584                            *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
5585        proto_tree_add_string(tree,hf_giop_type_string,tvb,
5586                              *offset-u_octet4,u_octet4,buf);
5587      }
5588
5589     g_free(buf);              /* dont forget */
5590     break;
5591   case tk_fixed:
5592     break;
5593   case tk_value:
5594     break;
5595   case tk_value_box:
5596     break;
5597   case tk_native:
5598     break;
5599   case tk_abstract_interface:
5600     break;
5601   default:
5602     g_warning("giop: Unknown typecode data type %u \n", data_type);
5603   break;
5604   } /* data_type */
5605
5606 }