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