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