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