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