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