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