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