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