HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-giop.c
blobd76df034d7eaafda3ef7aab42c41e57b69e2a1ba
1 /* packet-giop.c
2 * Routines for CORBA GIOP/IIOP packet disassembly
4 * Initial Code by,
5 * Laurent Deniel <laurent.deniel@free.fr>
6 * Craig Rodrigues <rodrigc@attbi.com>
8 * GIOP API extensions by,
9 * Frank Singleton <frank.singleton@ericsson.com>
10 * Trevor Shepherd <eustrsd@am1.ericsson.se>
12 * $Id$
14 * Wireshark - Network traffic analyzer
15 * By Gerald Combs <gerald@wireshark.org>
16 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 * TODO: -- FS
36 * 1. heuristic giop dissector table [started]
37 * 2. GUI options, see 20
38 * 3. Remove unneccessary reply_status in heuristic dissector calls (now
39 * part of MessageHeader) [done]
40 * 4. get_CDR_xxx should be passed an alignment offset value
41 * rather than GIOP_HEADER_SIZE, as alignment can also change in a
42 * octet stream when eg: encapsulation is used [done]
43 * 5. GIOP users should eventually get there own tvbuff, and
44 * not rely on the GIOP tvbuff, more robust
45 * 6. get_CDR_string,wchar,wstring etc should handle different
46 * GIOP versions [started]
47 * 7. Fix situation where req_id is not unique in a logfile [done, use FN/MFN, needs improving.]
49 * 8. Keep request_1_2 in step with request_1_1 [started]
50 * 9. Explicit module name dissection [done]
51 * 10. Decode IOR and put in a useful struct [IOR decode started]
52 * 11. Fix encapsulation of IOR etc and boundary [done]
53 * 12. handle get_CDR_typeCode() [started]
54 * 13. Handle different IOR profiles
55 * 14. Change printable_string to RETURN a new string, not to modify the old.
56 * or, new function, make_printable_string [done, make_printable_string]
58 * 15. Handle "TCKind", and forget about eg: enum translation to symbolic values
59 * otherwise need knowledge of sub dissectors data - YUK [done]
60 * 16. Handle multiple RepoId representations, besides IDL:Echo:1.0 (see 13.)
61 * 17. Pass subset of RepoID to explicit dissector.
62 * eg : If IDL:Mod1/Mod2/Int3:1.0 then pass "Mod1/Mode2/Int3" to sub dissector[done]
63 * 18. Better hashing algorithms
64 * 19. Handle hash collision properly .
65 * 20. Allow users to paste a stringified IOR into the GUI, and tie it
66 * to a sub_dissector.
67 * 21. Add complete_request_packet_list and complete_reply_packet_hash.[done]
68 * 22. Handle case where users click in any order, AND try and match
69 * REPLY msg to the correct REQUEST msg when we have a request_id collision.[done]
70 * 23. Clean up memory management for all those g_malloc's etc
71 * 24. register_giop_user_module could return a key for every distinct Module/Interface
72 * the sub_dissector uses. So, instead of strcmp()'s when handling the
73 * namespace of an operation, we could have a lookup table instead.
74 * 25. A few typedefs in the right place.
75 * 26 Improve handling of gchar * and use const gchar * where possible.
76 * 27. Read/write IOR etc to/from file, allows objkey hash to be built from
77 * external data [read done, write incomplete]
78 * 28. Call sub dissector only if tvb_offset_exists(). [Done, this is checked
79 * inside try_explicit_giop_dissector() ]
81 * 29. Make add/delete routine for objkey hash as it may be useful when say reading
82 * stringified IOR's from a file to add them to our hash. ie: There are other ways
83 * to populate our object key hash besides REPLY's to RESOLVE(request) [done]
85 * 30. Add routine to encode/decode stringified IOR's [decode done]
86 * 31. Add routine to read IOR's from file [done]
87 * 32. TypeCode -none-, needs decoding.
88 * 33. Complete dissect_data_for_typecode.
89 * 34. For complex TypeCodes need to check final offset against original offset + sequence length.
90 * 35. Update REQUEST/REPLY 1_2 according to IDL (eg; ServiceContextList etc).
91 * 36. Adding decode_ServiceContextList, incomplete.
92 * 37. Helper functions should not ALWAYS rely on header to find current endianness. It should
93 * be passed from user, eg Use stream_is_big_endian. [started]
94 * 38. Remove unwanted/unused function parameters, see decode_IOR [started]
95 * 40. Add sequence <IOP::TaggedComponent> components to IIOP IOR profile. Perhaps
96 * decode_IOP_TaggedComponents as a helper function. [done - NOT helper]
98 * 41. Make important field searchable from Message header. ie: Remove add_text_
99 * 42. Use sub-tree for decode_ServiceContextList, looks better.
100 * 43. dissect_reply_body, no exception dissector calls
101 * - call subdiss directly, as we already have handle.
102 * - add repoid to heuristic call also.
104 * 44. typedef using xxx_t in .h file.
105 * 45. Subdissectors should not be passed MessageHeader to find endianness and
106 * version, they should be passed directly ?
107 * 46. get_CDR_wchar and wstring need wide chars decoded (just dumped in
108 * any readable form at present, not handled well at all, suggestions welcome -- FS
109 * 47. Change ...add_text to ...add_xxx (ie use hf fields).
111 * 48. BUG - file load with a GIOP filter set, causes the FN/MFN data struct to be
112 * not initiated properly. Hit "Reload" as a workaround, til I fix this -- FS
119 * Intended Decode strategy:
120 * =========================
122 * Initial Pass
123 * ------------
124 * REQUEST: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
125 * and populate complete_request_packet_hash
127 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
129 * User Clicks
130 * -----------
132 * REQUEST: FN -> giop_sub_handle_t directly (via complete_request_packet_hash)
134 * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
135 * (via complete_request_packet_hash
138 * Limitations.
139 * ============
141 * 1. Request_ID's are unique only per connection.
143 * 2. You must be monitoring the network when the client does
144 * a REQUEST(resolve), otherwise I have no knowledge of the
145 * association between object_key and REPOID. I could talk to
146 * a Nameserver, but then I would start "generating" packets.
147 * This is probably not a good thing for a protocol analyser.
148 * Also, how could I decode logfiles offline.
150 * TODO -- Read stringified IORs from an input file.[done]
152 * 3. User clicks (REQUEST) is currently handle the same as
153 * the initial pass handling.
155 * ie: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
160 * Important Data Structures:
162 * giop_module_hash
163 * ----------------
165 * This is a hash table that maps IDL Module/Interface Names (Key)
166 * to sub_dissector handles, giop_sub_handle_t. It is populated
167 * by subdissectors, via register_giop_user_module(). This
168 * table is used when we have a REPOID, and explicitly wish to
169 * call the subdissector that has registered responsibility for
170 * that IDL module/interface.
173 * giop_sub_list
174 * -------------
176 * This singly linked list is used to hold entries for
177 * heuristic based subdissectors. It is populated by sub_dissectors
178 * wishing to be called via heuristic mechanisms. They do this
179 * via the register_giop_user() function.
182 * giop_objkey_hash
183 * ----------------
185 * This hash table maps object_key's (key) onto REPOID's (val).
186 * Once a client has REQUEST(resolve) an object , it knows about
187 * an object (interface) via its object_key (see IOR). So in order to follow
188 * packets that contain an object_key only, and to be able to forward it
189 * to the correct explicit subdissector, we need this table.
191 * So, I listen in on REQUEST(resolve) messages between client and
192 * Nameserver, and store the respones (REPLY/Objkey,Repo_ID) here.
194 * Also, stringified IOR's can be read from a file "IOR.txt" and used
195 * to populate this hash also.
198 * Other Data structures
199 * =======================
201 * These structures have been added to minimise the possibility
202 * of incorrectly interpreted packets when people click all
203 * over the place, in no particular order, when the request_id's are
204 * not unique as captured. If all request_is'd are unique, as captured, then
205 * we would not have to deal with this problem.
208 * When the logfile or packets are initially being processed, I will
209 * build 2 structures. The intent is to be able to map a REPLY message
210 * back to the most recent REQUEST message with the same Request_ID
211 * (TODO and matching port and IP address ??)
213 * Abbrevs:
214 * --------
216 * FN - Frame Number
217 * MFN - Matching Frame Number
220 * complete_request_packet_list
221 * ----------------------------
223 * This is a list that contains ALL the FN's that are REQUEST's, along with
224 * operation,request_id and giop_sub_handle_t
226 * complete_reply_packet_hash
227 * --------------------------
229 * This is a hash table. It is populated with FN (key) and MFN (val).
230 * This allows me to handle the case, where if you click on any REPLY
231 * message, I can lookup the matching request. This can improve
232 * the match rate between REQUEST and REPLY when people click in
233 * any old fashion, but is NOT foolproof.
235 * The algorithm I use to populate this hash during initial pass,
236 * is as follows.
238 * If packet is a REPLY, note the reqid, and then traverse backwards
239 * through the complete_request_packet_list from its tail, looking
240 * for a FN that has the same Request_id. Once found, take the found FN
241 * from complete_reply_packet_hash, and insert it into the MFN field
242 * of the complete_reply_packet_hash.
245 * See TODO for improvements to above algorithm.
247 * So now when people click on a REQUEST packet, I can call lookup the
248 * giop_sub_handle_t directly from complete_request_packet_list.
250 * And, when they click on a REPLY, I grab the MFN of this FN from
251 * complete_reply_packet_hash, then look that up in the complete_request_packet_list
252 * and call the sub_dissector directly.
254 * So, how do I differentiate between the initial processing of incoming
255 * packets, and a user clickin on one ? Good question.
257 * I leverage the pinfo_fd->flags.visited on a per frame
258 * basis.
260 * To quote from the ever helpful development list
262 * " When a capture file is initially loaded, all "visited" flags
263 * are 0. Wireshark then makes the first pass through file,
264 * sequentially dissecting each packet. After the packet is
265 * dissected the first time, "visited" is 1. (See the end of
266 * dissect_packet() in epan/packet.c; that's the code that
267 * sets "visited" to 1).
269 * By the time a user clicks on a packet, "visited" will already
270 * be 1 because Wireshark will have already done its first pass
271 * through the packets.
273 * Reload acts just like a normal Close/Open, except that it
274 * doesn't need to ask for a filename. So yes, the reload button
275 * clears the flags and re-dissects the file, just as if the file
276 * had been "opened". "
281 #include "config.h"
283 #include <string.h>
284 #include <stdio.h>
285 #include <errno.h>
286 #include <ctype.h>
287 #include <glib.h>
288 #include <math.h>
290 #include "isprint.h"
292 #include <epan/packet.h>
293 #include <epan/exceptions.h>
294 #include <epan/conversation.h>
295 #include <epan/wmem/wmem.h>
296 #include <epan/prefs.h>
297 #include <epan/expert.h>
299 #include "packet-giop.h"
300 #include "packet-ziop.h"
301 #include "packet-tcp.h"
302 #include <wsutil/file_util.h>
303 #include <wsutil/pint.h>
307 * Set to 1 for DEBUG output - TODO make this a runtime option
310 #define DEBUG 0
313 * ------------------------------------------------------------------------------------------+
314 * Private Helper function Declarations
315 * ------------------------------------------------------------------------------------------+
319 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
320 guint32 boundary, gboolean new_endianness,
321 const gchar *repobuf,
322 gboolean store_flag);
324 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
325 guint32 boundary, gboolean stream_is_big_endian, const gchar *repobuf);
327 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
328 guint32 boundary, gboolean stream_is_big_endian );
330 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
331 gboolean stream_is_big_endian,
332 guint32 boundary);
335 * ------------------------------------------------------------------------------------------+
336 * Data/Variables/Structs
337 * ------------------------------------------------------------------------------------------+
341 static int proto_giop = -1;
342 static int hf_giop_message_magic = -1;
343 static int hf_giop_message_major_version = -1;
344 static int hf_giop_message_minor_version = -1;
345 static int hf_giop_message_flags = -1;
346 static int hf_giop_message_flags_ziop_enabled = -1;
347 static int hf_giop_message_flags_ziop_supported = -1;
348 static int hf_giop_message_flags_fragment = -1;
349 static int hf_giop_message_flags_little_endian = -1;
350 static int hf_giop_message_type = -1;
351 static int hf_giop_message_size = -1;
352 static int hf_giop_repoid = -1;
353 static int hf_giop_req_id = -1;
354 static int hf_giop_req_operation_len = -1;
355 static int hf_giop_req_operation = -1;
356 static int hf_giop_req_principal_len = -1;
357 static int hf_giop_req_principal = -1;
358 static int hf_giop_string_length = -1;
359 static int hf_giop_sequence_length = -1;
360 static int hf_giop_profile_id = -1;
361 static int hf_giop_type_id = -1;
362 static int hf_giop_iiop_v_maj = -1;
363 static int hf_giop_iiop_v_min = -1;
364 static int hf_giop_endianness = -1; /* esp encapsulations */
365 /* static int hf_giop_compressed = -1; */
366 /* static int hf_giop_IOR_tag = -1; */
367 static int hf_giop_IIOP_tag = -1;
368 static int hf_giop_locale_status = -1;
369 static int hf_giop_addressing_disposition = -1;
370 static int hf_giop_profile_data = -1;
371 static int hf_giop_component_data = -1;
372 static int hf_giop_char_data = -1;
373 static int hf_giop_wchar_data = -1;
374 static int hf_giop_rt_corba_priority = -1;
375 static int hf_giop_context_data_len = -1;
376 static int hf_giop_context_data = -1;
377 static int hf_giop_target_address_discriminant = -1;
378 static int hf_giop_target_address_key_addr_len = -1;
379 static int hf_giop_target_address_key_addr = -1;
380 static int hf_giop_target_address_ref_addr_len = -1;
382 static int hf_giop_TCKind = -1;
383 static int hf_giop_typecode_count = -1;
384 static int hf_giop_typecode_default_used = -1;
385 static int hf_giop_typecode_digits = -1;
386 static int hf_giop_typecode_length = -1;
387 static int hf_giop_typecode_max_length = -1;
388 static int hf_giop_typecode_member_name = -1;
389 static int hf_giop_typecode_name = -1;
390 static int hf_giop_typecode_scale = -1;
391 static int hf_giop_typecode_ValueModifier = -1;
392 static int hf_giop_typecode_Visibility = -1;
394 static int hf_giop_type_boolean = -1;
395 static int hf_giop_type_char = -1;
396 static int hf_giop_type_double = -1;
397 static int hf_giop_type_enum = -1;
398 static int hf_giop_type_float = -1;
399 static int hf_giop_type_long = -1;
400 static int hf_giop_type_octet = -1;
401 static int hf_giop_type_short = -1;
402 static int hf_giop_type_string = -1;
403 static int hf_giop_type_ulong = -1;
404 static int hf_giop_type_ushort = -1;
406 static int hf_giop_iiop_host = -1;
407 static int hf_giop_iiop_port = -1;
408 static int hf_giop_iop_vscid = -1;
409 static int hf_giop_iop_scid = -1;
411 static int hf_giop_reply_status = -1;
412 static int hf_giop_exception_id = -1;
413 static int hf_giop_exception_len = -1;
414 static int hf_giop_objekt_key = -1;
415 static int hf_giop_rsp_expected = -1;
416 static int hf_giop_response_flag = -1;
417 static int hf_giop_reserved = -1;
418 static int hf_giop_objekt_key_len = -1;
419 static int hf_giop_type_id_len = -1;
420 static int hf_giop_stub_data = -1;
421 static int hf_giop_address_disp = -1;
422 static int hf_giop_reply_body = -1;
423 static int hf_giop_minor_code_value = -1;
424 static int hf_giop_completion_status = -1;
427 * (sub)Tree declares
430 static gint ett_giop = -1;
431 static gint ett_giop_header = -1;
432 static gint ett_giop_header_version = -1;
433 static gint ett_giop_message_flags = -1;
434 static gint ett_giop_reply = -1;
435 static gint ett_giop_request = -1;
436 static gint ett_giop_cancel_request = -1;
437 static gint ett_giop_locate_request = -1;
438 static gint ett_giop_locate_reply = -1;
439 static gint ett_giop_fragment = -1;
441 static gint ett_giop_scl = -1; /* ServiceContextList */
442 static gint ett_giop_scl_st1 = -1;
443 static gint ett_giop_ior = -1; /* IOR */
445 static expert_field ei_giop_unknown_typecode_datatype = EI_INIT;
446 static expert_field ei_giop_unknown_sign_value = EI_INIT;
447 static expert_field ei_giop_unknown_tckind = EI_INIT;
448 static expert_field ei_giop_length_too_big = EI_INIT;
449 static expert_field ei_giop_version_not_supported = EI_INIT;
450 static expert_field ei_giop_message_size_too_big = EI_INIT;
451 static expert_field ei_giop_invalid_v_minor = EI_INIT;
454 static const int *giop_message_flags[] = {
455 &hf_giop_message_flags_ziop_enabled,
456 &hf_giop_message_flags_ziop_supported,
457 &hf_giop_message_flags_fragment,
458 &hf_giop_message_flags_little_endian,
459 NULL
462 static dissector_handle_t data_handle;
463 static dissector_handle_t giop_tcp_handle;
465 #define GIOP_MESSAGE_FLAGS_ZIOP_ENABLED 0x08
466 #define GIOP_MESSAGE_FLAGS_ZIOP_SUPPORTED 0x04
467 #define GIOP_MESSAGE_FLAGS_FRAGMENT 0x02
468 #define GIOP_MESSAGE_FLAGS_ENDIANNESS 0x01
470 /* GIOP endianness */
472 static const value_string giop_endianness_vals[] = {
473 { 0x0, "Big Endian" },
474 { 0x1, "Little Endian" },
475 { 0, NULL}
478 static const value_string target_address_discriminant_vals[] = {
479 { 0x0, "KeyAddr" },
480 { 0x1, "ProfileAddr" },
481 { 0x2, "ReferenceAddr" },
482 { 0, NULL}
486 static const value_string sync_scope[] = {
487 { 0x0, "SYNC_NONE" },
488 { 0x1, "SYNC_WITH_TRANSPORT"},
489 { 0x2, "SYNC_WITH_SERVER"},
490 { 0x3, "SYNC_WITH_TARGET"},
491 { 0, NULL}
493 Bug fix:
494 https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=2800
495 http://ethereal.netmirror.org/lists/ethereal-users/200303/msg00135.html
497 static const value_string response_flags_vals[] = {
498 { 0x0, "SyncScope NONE or WITH_TRANSPORT" },
499 { 0x1, "SyncScope WITH_SERVER"},
500 { 0x3, "SyncScope WITH_TARGET"},
501 { 0, NULL}
504 /* Profile ID's */
506 static const value_string profile_id_vals[] = {
507 { 0x0, "TAG_INTERNET_IOP" },
508 { 0x1, "TAG_MULTIPLE_COMPONENTS"},
509 { 0x2, "TAG_SCCP_IOP"},
510 { 0x3, "TAG_UIPMC"},
511 { 0, NULL}
514 static const value_string giop_message_types[] = {
515 { 0x0, "Request" },
516 { 0x1, "Reply"},
517 { 0x2, "CancelRequest"},
518 { 0x3, "LocateRequest"},
519 { 0x4, "LocateReply"},
520 { 0x5, "CloseConnection"},
521 { 0x6, "MessageError"},
522 { 0x7, "Fragment"},
523 { 0, NULL}
526 static const value_string giop_locate_status_types[] = {
527 { 0x0, "Unknown Object" },
528 { 0x1, "Object Here"},
529 { 0x2, "Object Forward"},
530 { 0x3, "Object Forward Perm"},
531 { 0x4, "Loc System Exception"},
532 { 0x5, "Loc Needs Addressing Mode"},
533 { 0, NULL }
536 static const value_string tckind_vals[] = {
537 { 0, "tk_null"},
538 { 1, "tk_void"},
539 { 2, "tk_short"},
540 { 3, "tk_long"},
541 { 4, "tk_ushort"},
542 { 5, "tk_ulong"},
543 { 6, "tk_float"},
544 { 7, "tk_double"},
545 { 8, "tk_boolean"},
546 { 9, "tk_char"},
547 { 10, "tk_octet"},
548 { 11, "tk_any"},
549 { 12, "tk_TypeCode"},
550 { 13, "tk_Principal"},
551 { 14, "tk_objref"},
552 { 15, "tk_struct"},
553 { 16, "tk_union"},
554 { 17, "tk_enum"},
555 { 18, "tk_string"},
556 { 19, "tk_sequence"},
557 { 20, "tk_array"},
558 { 21, "tk_alias"},
559 { 22, "tk_except"},
560 { 23, "tk_longlong"},
561 { 24, "tk_ulonglong"},
562 { 25, "tk_longdouble"},
563 { 26, "tk_wchar"},
564 { 27, "tk_wstring"},
565 { 28, "tk_fixed"},
566 { 29, "tk_value"},
567 { 30, "tk_value_box"},
568 { 31, "tk_native"},
569 { 32, "tk_abstract_interface"},
570 { 0, NULL }
574 * These values are taken from the CORBA 3.0.2 standard,
575 * section 13.7.1 "Standard Service Contexts".
577 static const guint32 max_service_context_id = 0x10;
578 static const value_string service_context_ids[] = {
579 { 0x00, "TransactionService" },
580 { 0x01, "CodeSets"},
581 { 0x02, "ChainBypassCheck"},
582 { 0x03, "ChainBypassInfo"},
583 { 0x04, "LogicalThreadId"},
584 { 0x05, "BI_DIR_IIOP"},
585 { 0x06, "SendingContextRunTime"},
586 { 0x07, "INVOCATION_POLICIES"},
587 { 0x08, "FORWARDED_IDENTITY"},
588 { 0x09, "UnknownExceptionInfo"},
589 { 0x0a, "RTCorbaPriority"},
590 { 0x0b, "RTCorbaPriorityRange"},
591 { 0x0c, "FT_GROUP_VERSION"},
592 { 0x0d, "FT_REQUEST"},
593 { 0x0e, "ExceptionDetailMessage"},
594 { 0x0f, "SecurityAttributeService"},
595 { 0x10, "ActivityService"},
596 { 0, NULL }
600 * From Section 13.10.2.5 of the CORBA 3.0 spec.
602 * module CONV_FRAME {
603 * typedef unsigned long CodeSetId;
604 * struct CodeSetContext {
605 * CodeSetId char_data;
606 * CodeSetId wchar_data;
607 * };
608 * };
610 * Code sets are identified by a 32-bit integer id from OSF.
611 * See: ftp://ftp.opengroup.org/pub/code_set_registry
613 static const value_string giop_code_set_vals[] = {
614 { 0x00010001, "ISO_8859_1" },
615 { 0x00010002, "ISO_8859_2" },
616 { 0x00010003, "ISO_8859_3" },
617 { 0x00010004, "ISO_8859_4" },
618 { 0x00010005, "ISO_8859_5" },
619 { 0x00010006, "ISO_8859_6" },
620 { 0x00010007, "ISO_8859_7" },
621 { 0x00010008, "ISO_8859_8" },
622 { 0x00010009, "ISO_8859_9" },
623 { 0x0001000A, "ISO_8859_10" },
624 { 0x0001000F, "ISO_8859_15" },
625 { 0x00010020, "ISO_646" },
626 { 0x00010100, "ISO_UCS_2_LEVEL_1" },
627 { 0x00010101, "ISO_UCS_2_LEVEL_2" },
628 { 0x00010102, "ISO_UCS_2_LEVEL_3" },
629 { 0x00010104, "ISO_UCS_4_LEVEL_1" },
630 { 0x00010105, "ISO_UCS_4_LEVEL_2" },
631 { 0x00010106, "ISO_UCS_4_LEVEL_3" },
632 { 0x00010108, "ISO_UTF_8" },
633 { 0x00010109, "ISO_UTF_16" },
634 { 0x00030001, "JIS_X0201" },
635 { 0x00030004, "JIS_X0208_1978" },
636 { 0x00030005, "JIS_X0208_1983" },
637 { 0x00030006, "JIS_X0208_1990" },
638 { 0x0003000A, "JIS_X0212" },
639 { 0x00030010, "JIS_EUCJP" },
640 { 0x00040001, "KS_C5601" },
641 { 0x00040002, "KS_C5657" },
642 { 0x0004000A, "KS_EUCKR" },
643 { 0x00050001, "CNS_11643_1986" },
644 { 0x00050002, "CNS_11643_1992" },
645 { 0x0005000A, "CNS_EUCTW_1991" },
646 { 0x00050010, "CNS_EUCTW_1993" },
647 { 0x000B0001, "TIS_620_2529" },
648 { 0x000D0001, "TTB_CCDC" },
649 { 0x05000010, "OSF_JAPANESE_UJIS" },
650 { 0x05000011, "OSF_JAPANESE_SJIS_1" },
651 { 0x05000012, "OSF_JAPANESE_SJIS_2" },
652 { 0x05010001, "XOPEN_UTF_8" },
653 { 0x05020001, "JVC_EUCJP" },
654 { 0x05020002, "JVC_SJIS" },
655 { 0x10000001, "DEC_KANJI" },
656 { 0x10000002, "SUPER_DEC_KANJI" },
657 { 0x10000003, "DEC_SHIFT_JIS" },
658 { 0x10010001, "HP_ROMAN8" },
659 { 0x10010002, "HP_KANA8" },
660 { 0x10010003, "HP_ARABIC8" },
661 { 0x10010004, "HP_GREEK8" },
662 { 0x10010005, "HP_HEBREW8" },
663 { 0x10010006, "HP_TURKISH8" },
664 { 0x10010007, "HP15CN" },
665 { 0x10010008, "HP_BIG5" },
666 { 0x10010009, "HP_JAPANESE15__SJIS_" },
667 { 0x1001000A, "HP_SJISHI" },
668 { 0x1001000B, "HP_SJISPC" },
669 { 0x1001000C, "HP_UJIS" },
670 { 0x10020025, "IBM_037" },
671 { 0x10020111, "IBM_273" },
672 { 0x10020115, "IBM_277" },
673 { 0x10020116, "IBM_278" },
674 { 0x10020118, "IBM_280" },
675 { 0x1002011A, "IBM_282" },
676 { 0x1002011C, "IBM_284" },
677 { 0x1002011D, "IBM_285" },
678 { 0x10020122, "IBM_290" },
679 { 0x10020129, "IBM_297" },
680 { 0x1002012C, "IBM_300" },
681 { 0x1002012D, "IBM_301" },
682 { 0x100201A4, "IBM_420" },
683 { 0x100201A8, "IBM_424" },
684 { 0x100201B5, "IBM_437" },
685 { 0x100201F4, "IBM_500" },
686 { 0x10020341, "IBM_833" },
687 { 0x10020342, "IBM_834" },
688 { 0x10020343, "IBM_835" },
689 { 0x10020344, "IBM_836" },
690 { 0x10020345, "IBM_837" },
691 { 0x10020346, "IBM_838" },
692 { 0x10020347, "IBM_839" },
693 { 0x10020352, "IBM_850" },
694 { 0x10020354, "IBM_852" },
695 { 0x10020357, "IBM_855" },
696 { 0x10020358, "IBM_856" },
697 { 0x10020359, "IBM_857" },
698 { 0x1002035D, "IBM_861" },
699 { 0x1002035E, "IBM_862" },
700 { 0x1002035F, "IBM_863" },
701 { 0x10020360, "IBM_864" },
702 { 0x10020362, "IBM_866" },
703 { 0x10020364, "IBM_868" },
704 { 0x10020365, "IBM_869" },
705 { 0x10020366, "IBM_870" },
706 { 0x10020367, "IBM_871" },
707 { 0x1002036A, "IBM_874" },
708 { 0x1002036B, "IBM_875" },
709 { 0x10020370, "IBM_880" },
710 { 0x1002037B, "IBM_891" },
711 { 0x10020380, "IBM_896" },
712 { 0x10020381, "IBM_897" },
713 { 0x10020387, "IBM_903" },
714 { 0x10020388, "IBM_904" },
715 { 0x10020396, "IBM_918" },
716 { 0x10020399, "IBM_921" },
717 { 0x1002039A, "IBM_922" },
718 { 0x1002039E, "IBM_926" },
719 { 0x1002039F, "IBM_927" },
720 { 0x100203A0, "IBM_928" },
721 { 0x100203A1, "IBM_929" },
722 { 0x100203A2, "IBM_930" },
723 { 0x100203A4, "IBM_932" },
724 { 0x100203A5, "IBM_933" },
725 { 0x100203A6, "IBM_934" },
726 { 0x100203A7, "IBM_935" },
727 { 0x100203A8, "IBM_936" },
728 { 0x100203A9, "IBM_937" },
729 { 0x100203AA, "IBM_938" },
730 { 0x100203AB, "IBM_939" },
731 { 0x100203AD, "IBM_941" },
732 { 0x100203AE, "IBM_942" },
733 { 0x100203AF, "IBM_943" },
734 { 0x100203B2, "IBM_946" },
735 { 0x100203B3, "IBM_947" },
736 { 0x100203B4, "IBM_948" },
737 { 0x100203B5, "IBM_949" },
738 { 0x100203B6, "IBM_950" },
739 { 0x100203B7, "IBM_951" },
740 { 0x100203BB, "IBM_955" },
741 { 0x100203C4, "IBM_964" },
742 { 0x100203CA, "IBM_970" },
743 { 0x100203EE, "IBM_1006" },
744 { 0x10020401, "IBM_1025" },
745 { 0x10020402, "IBM_1026" },
746 { 0x10020403, "IBM_1027" },
747 { 0x10020410, "IBM_1040" },
748 { 0x10020411, "IBM_1041" },
749 { 0x10020413, "IBM_1043" },
750 { 0x10020416, "IBM_1046" },
751 { 0x10020417, "IBM_1047" },
752 { 0x10020440, "IBM_1088" },
753 { 0x10020449, "IBM_1097" },
754 { 0x1002044A, "IBM_1098" },
755 { 0x10020458, "IBM_1112" },
756 { 0x1002045A, "IBM_1114" },
757 { 0x1002045B, "IBM_1115" },
758 { 0x10020462, "IBM_1122" },
759 { 0x100204E2, "IBM_1250" },
760 { 0x100204E3, "IBM_1251" },
761 { 0x100204E4, "IBM_1252" },
762 { 0x100204E5, "IBM_1253" },
763 { 0x100204E6, "IBM_1254" },
764 { 0x100204E7, "IBM_1255" },
765 { 0x100204E8, "IBM_1256" },
766 { 0x100204E9, "IBM_1257" },
767 { 0x10020564, "IBM_1380" },
768 { 0x10020565, "IBM_1381" },
769 { 0x10020567, "IBM_1383" },
770 { 0x1002112C, "IBM_4396" },
771 { 0x10021352, "IBM_4946" },
772 { 0x10021354, "IBM_4948" },
773 { 0x10021357, "IBM_4951" },
774 { 0x10021358, "IBM_4952" },
775 { 0x10021359, "IBM_4953" },
776 { 0x10021360, "IBM_4960" },
777 { 0x10021364, "IBM_4964" },
778 { 0x10021365, "IBM_4965" },
779 { 0x100213A2, "IBM_5026" },
780 { 0x100213A7, "IBM_5031" },
781 { 0x100213AB, "IBM_5035" },
782 { 0x100213B8, "IBM_5048" },
783 { 0x100213B9, "IBM_5049" },
784 { 0x100213CB, "IBM_5067" },
785 { 0x100221A4, "IBM_8612" },
786 { 0x10022341, "IBM_9025" },
787 { 0x10022342, "IBM_9026" },
788 { 0x10022346, "IBM_9030" },
789 { 0x10022360, "IBM_9056" },
790 { 0x1002236A, "IBM_9066" },
791 { 0x100223A5, "IBM_9125" },
792 { 0x10026352, "IBM_25426" },
793 { 0x10026358, "IBM_25432" },
794 { 0x10026412, "IBM_1042" },
795 { 0x10027025, "IBM_28709" },
796 { 0x10028358, "IBM_33624" },
797 { 0x100283BA, "IBM_33722" },
798 { 0x10030001, "HTCSJIS" },
799 { 0x10030002, "HTCUJIS" },
800 { 0x10040001, "FUJITSU_U90" },
801 { 0x10040002, "FUJITSU_S90" },
802 { 0x10040003, "FUJITSU_R90" },
803 { 0x10040004, "EBCDIC_ASCII_AND_JEF" },
804 { 0x10040005, "EBCDIC_KATAKANA_AND_JEF" },
805 { 0x10040006, "EBCDIC_JAPANESE_ENGLISH_AND_JEF" },
806 { 0, NULL }
809 static value_string_ext giop_code_set_vals_ext = VALUE_STRING_EXT_INIT(giop_code_set_vals);
813 * TAGS for IOR Profiles
815 * Chapter 13 Corba 2.4.2
819 #define IOP_TAG_INTERNET_IOP 0
820 #define IOP_TAG_MULTIPLE_COMPONENTS 1
823 /* Max Supported versions */
825 static const guint GIOP_MAJOR = 1;
826 static const guint GIOP_MINOR = 2;
828 /* 1 Mb Used as a sanity check to ensure correct endian of message size field */
829 #define GIOP_MAX_MESSAGE_SIZE 1024*1000
832 static const value_string reply_status_types[] = {
833 { NO_EXCEPTION, "No Exception" } ,
834 { USER_EXCEPTION, "User Exception" } ,
835 { SYSTEM_EXCEPTION, "System Exception" } ,
836 { LOCATION_FORWARD, "Location Forward" } ,
837 { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
838 { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
839 { 0, NULL }
844 typedef enum LocateStatusType
846 UNKNOWN_OBJECT,
847 OBJECT_HERE,
848 OBJECT_FORWARD,
849 OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
850 LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
851 LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
853 LocateStatusType_t;
855 typedef struct LocateReplyHeader
857 guint32 request_id;
858 guint32 locate_status;
860 LocateReplyHeader_t;
864 * DATA - complete_request_list
867 static GList *giop_complete_request_list = NULL;
869 struct comp_req_list_entry {
870 guint32 fn; /* frame number */
871 gchar * operation; /* echo echoString */
872 giop_sub_handle_t *subh; /* handle to sub dissector */
873 guint32 reqid; /* request id */
874 gchar * repoid; /* repository ID */
877 typedef struct comp_req_list_entry comp_req_list_entry_t;
881 * DATA - complete_reply_hash
883 * Maps reply FN to request MFN
886 struct complete_reply_hash_key {
887 guint32 fn; /* reply frame number */
890 struct complete_reply_hash_val {
891 guint32 mfn; /* matching frame number (request) */
894 GHashTable *giop_complete_reply_hash = NULL; /* hash */
897 * DATA - Module Hash stuff to store data from register_giop_user_module
899 * ie: module (or interface ?) name, and ptr to sub_dissector handle
901 * With this knowledge, we can call a sub dissector directly,
902 * by :
904 * objkey -> repoid -> sub_dissector via registered module/interface
909 struct giop_module_key {
910 const gchar *module; /* module (interface?) name */
913 struct giop_module_val {
914 giop_sub_handle_t *subh; /* handle to sub dissector */
917 GHashTable *giop_module_hash = NULL; /* hash */
921 * DATA - GSList to store list of function (dissector) pointers.
922 * for heuristic dissection.
926 static GSList *giop_sub_list = NULL;
929 * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
930 * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
932 * With this knowledge, we can call a sub dissector directly later
933 * by :
935 * objkey -> repoid -> sub_dissector via registered module/interface
937 * rather than heuristic calls that do not provide operation context.
938 * (unless we pass the RepoID for a given objkey -- hmmm)
943 * Interesting operation list, add more if you want to save
944 * interesting data.
947 static const char giop_op_resolve[] = "resolve";
948 static const char giop_op_bind_new_context[] _U_ = "bind_new_context";
949 static const char giop_op_bind[] _U_ = "bind";
950 static const char giop_op_is_a[] = "_is_a";
953 * Enums for interesting local operations, that we may need to monitor
954 * with their subsequent replies
958 enum giop_op_val {
959 request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
960 request_bind_new_context_op_val, /* bind_new_context */
961 request_bind_op_val, /* bind */
962 request_get_INIT_op_val /* finding Nameserver */
968 * hash for mapping object keys onto object namespaces, so
969 * I can call the correct dissector.
975 * Where did I get the IOR from.
978 enum ior_src {
979 ior_src_req_res = 0, /* REQUEST (resolve) */
980 ior_src_file /* stringified IOR' in a file */
984 typedef enum ior_src ior_src_t;
989 * Enums for my lists and hash's
992 enum collection_data {
993 cd_heuristic_users = 0,
994 cd_module_hash,
995 cd_objkey_hash,
996 cd_complete_request_list,
997 cd_complete_reply_hash
1000 typedef enum collection_data collection_data_t;
1004 struct giop_object_key {
1005 const guint8 *objkey; /* ptr to object key */
1006 guint32 objkey_len; /* length */
1009 struct giop_object_val {
1010 guint8 *repo_id; /* ptr to Repository ID string */
1011 ior_src_t src; /* where did Iget this IOR from */
1014 GHashTable *giop_objkey_hash = NULL; /* hash */
1017 static gboolean giop_desegment = TRUE;
1018 static const char *giop_ior_file = "IOR.txt";
1021 * ------------------------------------------------------------------------------------------+
1022 * Private helper functions
1023 * ------------------------------------------------------------------------------------------+
1029 * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
1032 static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, const gchar * op, giop_sub_handle_t *sh ) {
1033 comp_req_list_entry_t * entry;
1035 entry = wmem_new(wmem_file_scope(), comp_req_list_entry_t);
1037 entry->fn = fn;
1038 entry->reqid = reqid;
1039 entry->subh = sh;
1040 entry->operation = wmem_strdup(wmem_file_scope(), op); /* duplicate operation for storage */
1041 entry->repoid = NULL; /* dont have yet */
1043 return g_list_append (list, entry); /* append */
1048 * Used to find an entry with matching Frame Number FN
1049 * in the complete_request_list list.
1052 static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
1054 GList * element; /* entry in list */
1055 comp_req_list_entry_t * entry_ptr = NULL;
1057 element = g_list_last(giop_complete_request_list); /* start from last */
1059 while(element) { /* valid list entry */
1060 entry_ptr = (comp_req_list_entry_t *)element->data; /* grab data pointer */
1061 if (entry_ptr->fn == fn) { /* similar FN */
1062 return entry_ptr;
1064 element = g_list_previous(element); /* try next previous */
1067 return NULL; /* no match so return NULL */
1072 * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
1074 * Call this when you know a FN and matching giop_sub_handle_t and repoid
1076 * This is done in say, try_explicit_dissector for example.
1080 static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
1082 comp_req_list_entry_t * entry = NULL;
1083 entry = find_fn_in_list(fn); /* grab FN data entry */
1085 if (entry) {
1086 entry->subh = sh;
1087 entry->repoid = g_strdup(repoid); /* copy and store */
1095 /* giop_complete_reply_hash "EQUAL" Functions */
1097 static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
1098 const struct complete_reply_hash_key *mk1 = (const struct complete_reply_hash_key *)v;
1099 const struct complete_reply_hash_key *mk2 = (const struct complete_reply_hash_key *)w;
1101 if (mk1->fn == mk2->fn) {
1102 return 1;
1105 return 0; /* found differences */
1108 /* giop_complete_reply_hash "HASH" Functions */
1110 static guint32 complete_reply_hash_fn(gconstpointer v) {
1111 guint32 val; /* init hash value */
1112 const struct complete_reply_hash_key *key = (const struct complete_reply_hash_key *)v;
1114 val = key->fn; /* simple and unique */
1116 return val;
1121 * Insert the FN and MFN together in our complete_reply_hash.
1124 static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
1126 struct complete_reply_hash_key key, *new_key;
1127 struct complete_reply_hash_val *val = NULL;
1129 key.fn = fn;
1131 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
1133 if (val) {
1134 return; /* FN collision */
1137 new_key = wmem_new(wmem_file_scope(), struct complete_reply_hash_key);
1138 new_key->fn = fn; /* save FN */
1140 val = wmem_new(wmem_file_scope(), struct complete_reply_hash_val);
1141 val->mfn = mfn; /* and MFN */
1143 g_hash_table_insert(giop_complete_reply_hash, new_key, val);
1148 * Find the MFN values from a given FN key.
1149 * Assumes the complete_reply_hash is already populated.
1152 static guint32 get_mfn_from_fn(guint32 fn) {
1154 struct complete_reply_hash_key key;
1155 struct complete_reply_hash_val *val = NULL;
1156 guint32 mfn = fn; /* save */
1158 key.fn = fn;
1159 val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
1161 if (val) {
1162 mfn = val->mfn; /* grab it */
1165 return mfn; /* mfn or fn if not found */
1170 * Attempt to find the MFN for this FN, and return it.
1171 * Return MFN if found, or just FN if not. This is
1172 * only used when we are building
1175 static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
1177 GList * element; /* last entry in list */
1178 comp_req_list_entry_t * entry_ptr = NULL;
1180 /* Need Some pretty snappy code */
1182 /* Loop back from current end of complete_request_list looking for */
1183 /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
1186 * As this routine is only called during initial pass of data,
1187 * and NOT when a user clicks, it is ok to start from Current
1188 * end of complete_request_list when searching for a match.
1189 * As that list is bing populated in the same order as FN's
1190 * are being read.
1192 * Also, can make check for same reqid more detailed, but I start
1193 * with reqid. Could add say port or address checks etc later ??
1197 element = g_list_last(giop_complete_request_list); /* get last */
1199 while(element) { /* valid list entry */
1200 entry_ptr = (comp_req_list_entry_t *)element->data; /* grab data pointer */
1201 if (entry_ptr->reqid == reqid) { /* similar reqid */
1202 return entry_ptr->fn; /* return MFN */
1204 element = g_list_previous(element); /* try next previous */
1207 return fn; /* no match so return FN */
1211 /* Module Hash "EQUAL" Functions */
1213 static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
1214 const struct giop_module_key *mk1 = (const struct giop_module_key *)v;
1215 const struct giop_module_key *mk2 = (const struct giop_module_key *)w;
1217 if (strcmp(mk1->module, mk2->module) == 0) {
1218 return 1;
1221 return 0; /* found differences */
1224 /* Module Hash "HASH" Functions */
1226 static guint32 giop_hash_module_hash(gconstpointer v) {
1228 int i,len;
1229 guint32 val = 0; /* init hash value */
1231 const struct giop_module_key *key = (const struct giop_module_key *)v;
1234 * Hmm, try this simple hashing scheme for now.
1235 * ie: Simple summation, FIX later -- FS
1240 len = (int)strlen(key->module);
1242 for (i=0; i<len; i++) {
1243 val += (guint8) key->module[i];
1246 return val;
1252 * ------------------------------------------------------------------------------------------+
1253 * Public Utility functions
1254 * ------------------------------------------------------------------------------------------+
1261 * Routine to allow giop users to register their sub dissector function, name, and
1262 * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
1263 * value returned from their proto_register_protocol(), so we can enable/disbale it
1264 * through the GUI (edit protocols).
1266 * This is used by try_explicit_giop_dissector() to find the
1267 * correct sub-dissector.
1271 void register_giop_user_module(giop_sub_dissector_t *sub, const gchar *name, const gchar *module, int sub_proto) {
1273 struct giop_module_key module_key, *new_module_key;
1274 struct giop_module_val *module_val = NULL;
1276 module_key.module = module; /* module name */
1278 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
1280 if (module_val) {
1281 return; /* module name collision */
1284 /* So, passed module name should NOT exist in hash at this point.*/
1286 #if DEBUG
1287 printf("giop:register_module: Adding Module %s to module hash \n", module);
1288 printf("giop:register_module: Module sub dissector name is %s \n", name);
1289 #endif
1291 new_module_key = (struct giop_module_key *)g_malloc(sizeof(struct giop_module_key));
1292 new_module_key->module = module; /* save Module or interface name from IDL */
1294 module_val = (struct giop_module_val *)g_malloc(sizeof(struct giop_module_val));
1296 module_val->subh = (giop_sub_handle_t *)g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
1298 module_val->subh->sub_name = name; /* save dissector name */
1299 module_val->subh->sub_fn = sub; /* save subdissector*/
1300 module_val->subh->sub_proto = find_protocol_by_id(sub_proto); /* save protocol_t for subdissector's protocol */
1302 g_hash_table_insert(giop_module_hash, new_module_key, module_val);
1309 /* Object Key Hash "EQUAL" Functions */
1311 static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
1312 const struct giop_object_key *v1 = (const struct giop_object_key *)v;
1313 const struct giop_object_key *v2 = (const struct giop_object_key *)w;
1315 if (v1->objkey_len != v2->objkey_len)
1316 return 0; /* no match because different length */
1318 /* Now do a byte comparison */
1320 if (memcmp(v1->objkey,v2->objkey, v1->objkey_len) == 0) {
1321 return 1; /* compares ok */
1324 #if DEBUG
1325 printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
1326 #endif
1328 return 0; /* found differences */
1331 /* Object Key Hash "HASH" Functions */
1333 static guint32 giop_hash_objkey_hash(gconstpointer v) {
1334 const struct giop_object_key *key = (const struct giop_object_key *)v;
1336 guint32 i;
1337 guint32 val = 0; /* init hash value */
1341 * Hmm, try this simple hashing scheme for now.
1342 * ie: Simple summation
1347 #if DEBUG
1348 printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
1349 #endif
1351 for (i=0; i< key->objkey_len; i++) {
1352 val += (guint8) key->objkey[i];
1355 return val;
1360 * Routine to take an object key octet sequence, and length, and ptr to
1361 * a (null terminated )repository ID string, and store them in the obect key hash.
1363 * Blindly Inserts even if it does exist, See TODO at top for reason.
1366 static void insert_in_objkey_hash(GHashTable *hash, const gchar *obj, guint32 len, const gchar *repoid, ior_src_t src) {
1368 struct giop_object_key objkey_key, *new_objkey_key;
1369 struct giop_object_val *objkey_val = NULL;
1371 objkey_key.objkey_len = len; /* length */
1372 objkey_key.objkey = obj; /* object key octet sequence */
1374 /* Look it up to see if it exists */
1376 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1378 /* CHANGED -- Same reqid, so abandon old entry */
1380 if (objkey_val) {
1381 g_hash_table_remove(hash, &objkey_key);
1384 /* So, passed key should NOT exist in hash at this point.*/
1386 new_objkey_key = wmem_new(wmem_file_scope(), struct giop_object_key);
1387 new_objkey_key->objkey_len = len; /* save it */
1388 new_objkey_key->objkey = (guint8 *) wmem_memdup(wmem_file_scope(), obj,len); /* copy from object and allocate ptr */
1390 objkey_val = wmem_new(wmem_file_scope(), struct giop_object_val);
1391 objkey_val->repo_id = wmem_strdup(wmem_file_scope(), repoid); /* duplicate and store Respository ID string */
1392 objkey_val->src = src; /* where IOR came from */
1395 #if DEBUG
1396 printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
1397 objkey_val->repo_id, new_objkey_key->objkey_len);
1398 #endif
1400 g_hash_table_insert(hash, new_objkey_key, objkey_val);
1407 * convert an ascii char representing a hex value,
1408 * to a numeric value.
1410 * returns value, or -1 if problem.
1414 static gint8 hex_char_to_val(guchar c){
1415 gint8 retval ;
1417 if (!isxdigit(c)) {
1418 return -1;
1420 if (isdigit(c)) {
1421 retval = c - 48; /* convert digit */
1422 return retval;
1425 c = toupper(c); /* convert to uppercase */
1426 if (c >= 'A' && c <= 'F') {
1427 retval = c - 55;
1428 return retval;
1430 else {
1431 return -1;
1437 * Convert from stringified IOR of the kind IOR:af4f7e459f....
1438 * to an IOR octet sequence.
1440 * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
1441 * grab repoid etc for our objkey hash.
1445 static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
1446 gint8 tmpval_lsb;
1447 gint8 tmpval_msb;
1448 gint8 tmpval; /* complete value */
1449 guint32 i;
1451 *out = wmem_alloc0_array(wmem_packet_scope(), guint8, in_len); /* allocate buffer */
1453 if (*out == NULL) {
1454 return 0;
1457 /* skip past IOR: and convert character pairs to guint8 */
1459 for (i=4; i<in_len-1; i+=2) {
1460 if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
1462 if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
1463 g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
1467 if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
1468 g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
1471 tmpval = tmpval_msb << 4;
1472 tmpval += tmpval_lsb;
1473 (*out)[(i-4)/2] = (guint8) tmpval;
1476 else {
1477 /* hmm */
1478 break;
1483 return (i-4)/2; /* length */
1490 * Simple "get a line" routine, copied from somewhere :)
1494 static int giop_getline(FILE *fp, gchar *line, int maxlen) {
1496 if (fgets(line,maxlen,fp) == NULL)
1497 return 0;
1498 else
1499 return (int)strlen(line);
1505 * Read a list of stringified IOR's from a named file, convert to IOR's
1506 * and store in object key hash
1509 static void read_IOR_strings_from_file(const gchar *name, int max_iorlen) {
1510 guchar *buf; /* NOTE reused for every line */
1511 int len;
1512 int ior_val_len; /* length after unstringifying. */
1513 FILE *fp;
1514 guint8 *out; /* ptr to unstringified IOR */
1515 tvbuff_t *tvb; /* temp tvbuff for dissectin IORs */
1516 guint32 my_offset = 0;
1517 gboolean stream_is_big_endian;
1520 fp = ws_fopen(name,"r"); /* open read only */
1522 if (fp == NULL) {
1523 if (errno == EACCES)
1524 fprintf(stderr, "Error opening file %s for reading: %s\n", name, g_strerror(errno));
1525 return;
1528 buf = (guchar *)wmem_alloc0(wmem_packet_scope(), max_iorlen+1); /* input buf */
1530 while ((len = giop_getline(fp,buf,max_iorlen+1)) > 0) {
1531 my_offset = 0; /* reset for every IOR read */
1533 ior_val_len = string_to_IOR(buf,len,&out); /* convert */
1535 if(ior_val_len>0) {
1537 /* XXX - can this throw an exception in this case? If so, we
1538 need to catch it and clean up, but we really shouldn't allow
1539 it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
1540 exception. */
1542 tvb = tvb_new_real_data(out, ior_val_len, ior_val_len);
1544 stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
1545 decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
1547 tvb_free(tvb);
1552 fclose(fp); /* be nice */
1558 * Init routine, setup our request hash stuff, or delete old ref's
1560 * Cannot setup the module hash here as my init() may not be called before
1561 * users start registering. So I will move the module_hash stuff to
1562 * proto_register_giop, as is done with packet-rpc
1566 * Also, setup our objectkey/repoid hash here.
1570 static void giop_init(void) {
1574 * Create objkey/repoid hash, use my "equal" and "hash" functions.
1575 * Note: keys and values are se_alloc'd so they don't need to be freed.
1579 if (giop_objkey_hash)
1580 g_hash_table_destroy(giop_objkey_hash);
1583 * Create hash, use my "equal" and "hash" functions.
1587 giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
1591 * Create complete_reply_hash, use my "equal" and "hash" functions.
1592 * Note: keys and values are se_alloc'd so they don't need to be freed.
1596 if (giop_complete_reply_hash)
1597 g_hash_table_destroy(giop_complete_reply_hash);
1600 * Create hash, use my "equal" and "hash" functions.
1604 giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
1608 * Free giop_complete_request_list (if necessary)
1609 * Note: The data elements are se_alloc'd so only the
1610 * actual list elements need to be freed.
1613 if (giop_complete_request_list) {
1614 g_list_free(giop_complete_request_list);
1615 giop_complete_request_list = NULL;
1618 read_IOR_strings_from_file(giop_ior_file, 600);
1625 * Insert an entry in the GIOP Heuristic User table.
1626 * Uses a GList.
1627 * Uses giop_sub_handle_t to wrap giop user info.
1631 void register_giop_user(giop_sub_dissector_t *sub, const gchar *name, int sub_proto) {
1633 giop_sub_handle_t *subh;
1635 subh = (giop_sub_handle_t *)g_malloc(sizeof (giop_sub_handle_t));
1637 subh->sub_name = name;
1638 subh->sub_fn = sub;
1639 subh->sub_proto = find_protocol_by_id(sub_proto); /* protocol_t for sub dissectors's proto_register_protocol() */
1641 giop_sub_list = g_slist_append (giop_sub_list, subh);
1647 * Lookup an object key in our object key hash, and return the corresponding
1648 * Repo Id.
1652 static gchar * get_repoid_from_objkey(GHashTable *hash, const guint8 *obj, guint32 len) {
1654 struct giop_object_key objkey_key;
1655 struct giop_object_val *objkey_val = NULL;
1657 objkey_key.objkey_len = len; /* length */
1658 objkey_key.objkey = obj; /* object key octet sequence */
1660 /* Look it up to see if it exists */
1662 objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
1664 if (objkey_val) {
1665 #if DEBUG
1666 printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
1667 #endif
1668 return objkey_val->repo_id; /* found */
1671 #if DEBUG
1672 printf("FAILED Lookup of object key \n" );
1673 #endif
1675 return NULL; /* not found */
1681 * Extract top level module/interface from repoid
1683 * eg from - "IDL:Echo/interface1:1.0"
1684 * get "Echo"
1686 * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
1687 * get linux.org/Penguin/Teeth
1690 * User must free returned ptr after use.
1692 * TODO -- generalize for other Repoid encodings
1695 static gchar * get_modname_from_repoid(gchar *repoid) {
1697 gchar *modname = NULL;
1698 gchar c = 'a';
1699 guint8 stop_mod = 0; /* Index of last character of modname in Repoid */
1700 guint8 start_mod = 4; /* Index where Module name starts in repoid */
1701 int i;
1703 /* Must start with IDL: , otherwise I get confused */
1705 if (g_ascii_strncasecmp("IDL:",repoid,4))
1706 return NULL;
1708 /* Looks like a RepoID to me, so get Module or interface name */
1710 /* TODO -- put some code here to get Module name */
1712 for(i=4; c != '\0'; i++) {
1713 c = repoid[i];
1714 stop_mod = i; /* save */
1715 if (c == ':' ) /* delimiters */
1716 break;
1720 /* Now create a new string based on start and stop and \0 */
1722 modname = g_strndup(repoid+4, stop_mod - start_mod);
1724 return modname;
1729 * DEBUG CODE
1734 #if DEBUG
1736 * Display a "module" hash entry
1739 static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
1741 struct giop_module_val *mv = (struct giop_module_val *) val;
1742 struct giop_module_key *mk = (struct giop_module_key *) key;
1744 printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
1746 return;
1751 * Display a "complete_reply " hash entry
1754 static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
1756 struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
1757 struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
1759 printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
1761 return;
1767 * Display an "objkey" hash entry
1770 static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
1771 guint32 i;
1772 struct giop_object_val *mv = (struct giop_object_val *) val;
1773 struct giop_object_key *mk = (struct giop_object_key *) key;
1776 printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
1778 for (i=0; i<mk->objkey_len; i++) {
1779 printf("%.2x ", mk->objkey[i]);
1783 * If read from file, mark it as such..
1786 if(mv->src == 0) {
1787 printf(", Repo ID = %s \n", mv->repo_id);
1789 else {
1790 printf(", Repo ID = %s , (file) \n", mv->repo_id);
1793 return;
1798 * Display all giop_sub_list (GSList) entries
1801 static void display_heuristic_user_list() {
1802 int i;
1803 int len;
1804 giop_sub_handle_t *subh; /* handle */
1806 /* Get length of list */
1807 len = g_slist_length(giop_sub_list); /* find length */
1809 if (len == 0)
1810 return;
1812 for (i=0; i<len; i++) {
1813 subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
1814 printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
1820 * Display all complete_request_list (GList) entries
1823 static void display_complete_request_list() {
1824 int i;
1825 int len;
1826 comp_req_list_entry_t *entry;
1828 /* Get length of list */
1829 len = g_list_length(giop_complete_request_list); /* find length */
1831 if (len == 0)
1832 return;
1834 for (i=0; i<len; i++) {
1835 entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
1836 printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
1837 entry->reqid,entry->operation, entry->repoid);
1845 /* Dump Hash/List contents
1847 * collection_type specifies the list or hash to dump
1851 static void giop_dump_collection(collection_data_t collection_type) {
1853 switch(collection_type) {
1854 case cd_heuristic_users:
1855 printf("+----------------------------------------------+ \n");
1856 printf("+-------------- Heuristic User (Begin) --------+ \n");
1857 printf("+----------------------------------------------+ \n");
1859 display_heuristic_user_list();
1861 printf("+----------------------------------------------+ \n");
1862 printf("+-------------- Heuristic User (End) ----------+ \n");
1863 printf("+----------------------------------------------+ \n");
1865 break;
1867 case cd_complete_request_list:
1868 printf("+----------------------------------------------+ \n");
1869 printf("+------------- Complete Request List (Begin) --+ \n");
1870 printf("+----------------------------------------------+ \n");
1872 display_complete_request_list();
1874 printf("+----------------------------------------------+ \n");
1875 printf("+------------ Complete Request List (End) -----+ \n");
1876 printf("+----------------------------------------------+ \n");
1878 break;
1880 case cd_module_hash:
1881 printf("+----------------------------------------------+ \n");
1882 printf("+-------------- Module (Begin) ----------------+ \n");
1883 printf("+----------------------------------------------+ \n");
1885 g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
1887 printf("+----------------------------------------------+ \n");
1888 printf("+-------------- Module ( End) -----------------+ \n");
1889 printf("+----------------------------------------------+ \n\n");
1891 break;
1893 case cd_objkey_hash:
1894 printf("+----------------------------------------------+ \n");
1895 printf("+-------------- Objkey (Begin) ----------------+ \n");
1896 printf("+----------------------------------------------+ \n");
1898 g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
1900 printf("+----------------------------------------------+ \n");
1901 printf("+-------------- Objkey (End) ------------------+ \n");
1902 printf("+----------------------------------------------+ \n\n");
1904 break;
1906 case cd_complete_reply_hash:
1907 printf("+----------------------------------------------+ \n");
1908 printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
1909 printf("+----------------------------------------------+ \n");
1911 g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
1913 printf("+----------------------------------------------+ \n");
1914 printf("+------------- Complete_Reply_Hash (End) ------+ \n");
1915 printf("+----------------------------------------------+ \n");
1917 break;
1919 default:
1921 printf("giop: giop_dump_collection: Unknown type \n");
1929 #endif /* DEBUG */
1932 * Loop through all subdissectors, and call them until someone
1933 * answers (returns TRUE). This function then returns TRUE, otherwise
1934 * it return FALSE
1936 * But skip a subdissector if it has been disabled in GUI "edit protocols".
1939 static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 *offset,
1940 MessageHeader *header, const gchar *operation ) {
1942 int i,len;
1943 gboolean res = FALSE; /* result of calling a heuristic sub dissector */
1944 giop_sub_handle_t *subh = NULL;
1945 const char *saved_proto;
1947 len = g_slist_length(giop_sub_list); /* find length */
1949 if (len == 0)
1950 return FALSE;
1953 guint32 message_size;
1954 gboolean stream_is_big_endian = is_big_endian (header);
1956 if (stream_is_big_endian)
1957 message_size = pntohl (&header->message_size);
1958 else
1959 message_size = pletohl (&header->message_size);
1961 if (*offset > message_size)
1962 return FALSE;
1965 saved_proto = pinfo->current_proto;
1966 for (i=0; i<len; i++) {
1967 subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
1969 if (proto_is_protocol_enabled(subh->sub_proto)) {
1970 pinfo->current_proto =
1971 proto_get_protocol_short_name(subh->sub_proto);
1972 res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
1973 if (res) {
1974 pinfo->current_proto = saved_proto;
1975 return TRUE; /* found one, lets return */
1977 } /* protocol_is_enabled */
1978 } /* loop */
1980 col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
1982 pinfo->current_proto = saved_proto;
1983 return res; /* result */
1989 * Find the matching repoid in the module hash and call
1990 * the dissector function if offset exists.
1993 * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
1994 * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
2000 static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
2001 MessageHeader *header, const gchar *operation, gchar *repoid ) {
2003 giop_sub_handle_t *subdiss = NULL; /* handle */
2004 gboolean res = FALSE;
2005 gchar *modname = NULL;
2006 struct giop_module_key module_key;
2007 struct giop_module_val *module_val = NULL;
2008 const char *saved_proto;
2012 * Get top level module/interface from complete repoid
2015 modname = get_modname_from_repoid(repoid);
2016 if (modname == NULL) {
2017 return res; /* unknown module name */
2021 /* Search for Module or interface name */
2023 module_key.module = modname; /* module name */
2024 module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
2026 if (module_val == NULL) {
2027 return res; /* module not registered */
2030 subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
2032 if (subdiss) {
2033 /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
2034 /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
2035 /* but only if user not clicking */
2037 if (!pinfo->fd->flags.visited)
2038 add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
2041 /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
2043 if (tvb_offset_exists(tvb, *offset)) {
2044 #if DEBUG
2045 printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
2046 #endif
2048 if (proto_is_protocol_enabled(subdiss->sub_proto)) {
2050 saved_proto = pinfo->current_proto;
2051 pinfo->current_proto =
2052 proto_get_protocol_short_name(subdiss->sub_proto);
2053 res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
2054 pinfo->current_proto = saved_proto;
2056 } /* protocol_is_enabled */
2057 } /* offset exists */
2058 } /* subdiss */
2060 return res; /* return result */
2065 /* Take in an array of char and create a new ephemeral string.
2066 * Replace non-printable characters with periods.
2068 * The array may contain \0's so dont use strdup
2069 * The string is \0 terminated, and thus longer than
2070 * the initial sequence.
2073 gchar * make_printable_string (const gchar *in, guint32 len) {
2074 guint32 i = 0;
2075 gchar *print_string = NULL;
2077 print_string = (gchar * )wmem_alloc0(wmem_packet_scope(), len + 1); /* make some space and zero it */
2078 memcpy(print_string, in, len); /* and make a copy of input data */
2080 for(i=0; i < len; i++) {
2081 if( !isprint( (unsigned char)print_string[i] ) )
2082 print_string[i] = '.';
2085 return print_string; /* return ptr */
2088 /* Determine the byte order from the GIOP MessageHeader */
2090 gboolean is_big_endian (MessageHeader * header) {
2091 gboolean big_endian = FALSE;
2093 switch (header->GIOP_version.minor) {
2094 case 2:
2095 case 1:
2096 if (header->flags & GIOP_MESSAGE_FLAGS_ENDIANNESS)
2097 big_endian = FALSE;
2098 else
2099 big_endian = TRUE;
2100 break;
2101 case 0:
2102 if (header->flags)
2103 big_endian = FALSE;
2104 else
2105 big_endian = TRUE;
2106 break;
2107 default:
2108 break;
2110 return big_endian;
2116 * Calculate new offset, based on the current offset, and user supplied
2117 * "offset delta" value, and the alignment requirement.
2121 * eg: Used for GIOP 1.2 where Request and Reply bodies are
2122 * aligned on 8 byte boundaries.
2125 static void set_new_alignment(int *offset, int delta, int alignment) {
2127 while( ( (*offset + delta) % alignment) != 0)
2128 ++(*offset);
2134 * Helper functions for dissecting TypeCodes
2136 * These functions decode the complex parameter lists
2137 * of TypeCodes as defined in the CORBA spec chapter 15.
2141 * For a given data type, given by a TypeCode gets the associated data
2142 * and displays it in the relevant tree.
2145 static void dissect_data_for_typecode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2146 proto_item *item, gint *offset,
2147 gboolean stream_is_big_endian, guint32 boundary,
2148 MessageHeader * header, guint32 data_type ) {
2150 gboolean my_boolean; /* boolean */
2152 gint8 s_octet1; /* signed int8 */
2153 guint8 u_octet1; /* unsigned int8 */
2155 gint16 s_octet2; /* signed int16 */
2156 guint16 u_octet2; /* unsigned int16 */
2158 gint32 s_octet4; /* signed int32 */
2159 guint32 u_octet4; /* unsigned int32 */
2161 gdouble my_double; /* double */
2162 gfloat my_float; /* float */
2164 const gchar *buf = NULL; /* ptr to string buffer */
2166 /* Grab the data according to data type */
2168 switch (data_type) {
2169 case tk_null:
2170 /* nothing to decode */
2171 break;
2172 case tk_void:
2173 /* nothing to decode */
2174 break;
2175 case tk_short:
2176 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
2177 proto_tree_add_int(tree, hf_giop_type_short, tvb, *offset-2, 2, s_octet2);
2178 break;
2179 case tk_long:
2180 s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
2181 proto_tree_add_int(tree, hf_giop_type_long, tvb, *offset-4, 4, s_octet4);
2182 break;
2183 case tk_ushort:
2184 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
2185 proto_tree_add_uint(tree, hf_giop_type_ushort,tvb, *offset-2, 2, u_octet2);
2186 break;
2187 case tk_ulong:
2188 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2189 proto_tree_add_uint(tree, hf_giop_type_ulong, tvb, *offset-4, 4, u_octet4);
2190 break;
2191 case tk_float:
2192 my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
2193 proto_tree_add_double(tree, hf_giop_type_float, tvb, *offset-4, 4, my_float);
2194 break;
2195 case tk_double:
2196 my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
2197 proto_tree_add_double(tree,hf_giop_type_double, tvb, *offset-8, 8, my_double);
2198 break;
2199 case tk_boolean:
2200 my_boolean = get_CDR_boolean(tvb,offset);
2201 proto_tree_add_boolean(tree, hf_giop_type_boolean, tvb, *offset-1, 1, my_boolean);
2202 break;
2203 case tk_char:
2204 u_octet1 = get_CDR_char(tvb,offset);
2205 proto_tree_add_uint(tree, hf_giop_type_char, tvb, *offset-1, 1, u_octet1);
2206 break;
2207 case tk_octet:
2208 u_octet1 = get_CDR_octet(tvb,offset);
2209 proto_tree_add_uint(tree, hf_giop_type_octet, tvb, *offset-1, 1, u_octet1);
2210 break;
2211 case tk_any:
2212 get_CDR_any(tvb, pinfo, tree, item, offset, stream_is_big_endian, boundary, header);
2213 break;
2214 case tk_TypeCode:
2215 get_CDR_typeCode(tvb, pinfo, tree, offset, stream_is_big_endian, boundary, header);
2216 break;
2217 case tk_Principal:
2218 break;
2219 case tk_objref:
2220 break;
2221 case tk_struct:
2222 break;
2223 case tk_union:
2224 break;
2225 case tk_enum:
2226 u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
2227 proto_tree_add_uint(tree, hf_giop_type_enum, tvb, *offset-4, 4, u_octet4);
2228 break;
2229 case tk_string:
2230 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
2231 proto_tree_add_uint(tree, hf_giop_string_length, tvb,
2232 *offset-u_octet4-4, 4, u_octet4);
2233 if (u_octet4 > 0) {
2234 proto_tree_add_string(tree,hf_giop_type_string,tvb,
2235 *offset-u_octet4,u_octet4,buf);
2237 break;
2238 case tk_sequence:
2239 break;
2240 case tk_array:
2241 break;
2242 case tk_alias:
2243 break;
2244 case tk_except:
2245 break;
2246 case tk_longlong:
2247 break;
2248 case tk_ulonglong:
2249 break;
2250 case tk_longdouble:
2251 break;
2252 case tk_wchar:
2253 s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
2254 if (tree) {
2255 if (s_octet1 < 0) { /* no size to add to tree */
2256 proto_tree_add_string(tree,hf_giop_type_string,tvb,
2257 *offset+s_octet1, (-s_octet1), buf);
2258 } else {
2259 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
2260 *offset-s_octet1-1, 1, s_octet1);
2261 proto_tree_add_string(tree,hf_giop_type_string,tvb,
2262 *offset-s_octet1, s_octet1, buf);
2265 break;
2266 case tk_wstring:
2267 u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
2268 if (tree) {
2269 proto_tree_add_uint(tree, hf_giop_string_length, tvb,
2270 *offset-u_octet4-4, 4, u_octet4);
2271 proto_tree_add_string(tree, hf_giop_type_string, tvb,
2272 *offset-u_octet4, u_octet4, buf);
2274 break;
2275 case tk_fixed:
2276 break;
2277 case tk_value:
2278 break;
2279 case tk_value_box:
2280 break;
2281 case tk_native:
2282 break;
2283 case tk_abstract_interface:
2284 break;
2285 default:
2286 expert_add_info_format(pinfo, item, &ei_giop_unknown_typecode_datatype, "Unknown typecode data type %u", data_type);
2287 break;
2292 * gets a TypeCode complex string parameter and
2293 * displays it in the relevant tree.
2296 static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2297 gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
2299 guint32 u_octet4; /* unsigned int32 */
2300 const gchar *buf; /* ptr to string buffer */
2302 /* get string */
2303 u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
2304 proto_tree_add_uint(tree, hf_giop_string_length, tvb,
2305 *offset-u_octet4-4, 4, u_octet4);
2306 if (u_octet4 > 0) {
2307 proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
2311 static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2312 gboolean stream_is_big_endian, guint32 boundary) {
2314 guint32 new_boundary; /* new boundary for encapsulation */
2315 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2317 /*guint32 seqlen;*/ /* sequence length */
2319 /* get sequence length, new endianness and boundary for encapsulation */
2320 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2321 stream_is_big_endian, boundary,
2322 &new_stream_is_big_endian, &new_boundary);
2324 /* get repository ID */
2325 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2326 hf_giop_repoid);
2328 /* get name */
2329 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2330 hf_giop_typecode_name);
2335 static void dissect_tk_struct_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset,
2336 gboolean stream_is_big_endian, guint32 boundary,
2337 MessageHeader * header ) {
2339 guint32 new_boundary; /* new boundary for encapsulation */
2340 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2342 guint32 count; /* parameter count (of tuples) */
2343 /*guint32 seqlen;*/ /* sequence length */
2344 guint32 i; /* loop index */
2346 /* get sequence length new endianness and boundary for encapsulation */
2347 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2348 stream_is_big_endian, boundary,
2349 &new_stream_is_big_endian, &new_boundary);
2351 /* get repository ID */
2352 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2353 hf_giop_repoid);
2355 /* get name */
2356 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2357 hf_giop_typecode_name);
2359 /* get count of tuples */
2360 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
2361 if (tree) {
2362 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
2363 *offset-(int)sizeof(count),4,count);
2366 /* get all tuples */
2367 for (i=0; i< count; i++) {
2368 /* get member name */
2369 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2370 hf_giop_typecode_member_name);
2372 /* get member type */
2373 get_CDR_typeCode(tvb, pinfo, tree, offset, new_stream_is_big_endian, new_boundary,header);
2379 static void dissect_tk_union_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item* item,
2380 gint *offset, gboolean stream_is_big_endian, guint32 boundary,
2381 MessageHeader * header) {
2383 guint32 new_boundary; /* new boundary for encapsulation */
2384 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2386 guint32 TCKind; /* TypeCode */
2387 gint32 s_octet4; /* signed int32 */
2389 guint32 count; /* parameter count (of tuples) */
2390 /*guint32 seqlen;*/ /* sequence length */
2391 guint32 i; /* loop index */
2393 /* get sequence length, new endianness and boundary for encapsulation */
2394 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2395 stream_is_big_endian, boundary,
2396 &new_stream_is_big_endian, &new_boundary);
2398 /* get repository ID */
2399 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2400 hf_giop_repoid);
2402 /* get name */
2403 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2404 hf_giop_typecode_name);
2406 /* get discriminant type */
2407 TCKind = get_CDR_typeCode(tvb, pinfo, tree, offset, new_stream_is_big_endian, new_boundary, header);
2409 /* get default used */
2410 s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
2411 proto_tree_add_int(tree, hf_giop_typecode_default_used, tvb,
2412 *offset-4, 4, s_octet4);
2414 /* get count of tuples */
2415 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
2416 proto_tree_add_uint(tree, hf_giop_typecode_count, tvb, *offset-4, 4, count);
2418 /* get all tuples */
2419 for (i=0; i< count; i++) {
2420 /* get label value, based on TCKind above */
2421 dissect_data_for_typecode(tvb, pinfo, tree, item, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
2423 /* get member name */
2424 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2425 hf_giop_typecode_member_name);
2427 /* get member type */
2428 get_CDR_typeCode(tvb, pinfo, tree, offset, new_stream_is_big_endian, new_boundary, header);
2434 static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2435 gboolean stream_is_big_endian, guint32 boundary) {
2437 guint32 new_boundary; /* new boundary for encapsulation */
2438 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2440 guint32 count; /* parameter count (of tuples) */
2441 /*guint32 seqlen;*/ /* sequence length */
2442 guint32 i; /* loop index */
2444 /* get sequence length, new endianness and boundary for encapsulation */
2445 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2446 stream_is_big_endian, boundary,
2447 &new_stream_is_big_endian, &new_boundary);
2449 /* get repository ID */
2450 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2451 hf_giop_repoid);
2453 /* get name */
2454 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2455 hf_giop_typecode_name);
2457 /* get count of tuples */
2458 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
2459 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
2460 *offset-4, 4, count);
2462 /* get all tuples */
2463 for (i=0; i< count; i++) {
2464 /* get member name */
2465 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2466 hf_giop_typecode_member_name);
2472 static void dissect_tk_sequence_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset,
2473 gboolean stream_is_big_endian, guint32 boundary,
2474 MessageHeader * header) {
2476 guint32 new_boundary; /* new boundary for encapsulation */
2477 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2479 guint32 u_octet4; /* unsigned int32 */
2481 /*guint32 seqlen;*/ /* sequence length */
2483 /* get sequence length, new endianness and boundary for encapsulation */
2484 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2485 stream_is_big_endian, boundary,
2486 &new_stream_is_big_endian, &new_boundary);
2488 /* get element type */
2489 get_CDR_typeCode(tvb, pinfo, tree, offset, new_stream_is_big_endian, new_boundary, header);
2491 /* get max length */
2492 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2493 proto_tree_add_uint(tree, hf_giop_typecode_max_length, tvb,
2494 *offset-4, 4, u_octet4);
2498 static void dissect_tk_array_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset,
2499 gboolean stream_is_big_endian, guint32 boundary,
2500 MessageHeader * header) {
2502 guint32 new_boundary; /* new boundary for encapsulation */
2503 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2505 guint32 u_octet4; /* unsigned int32 */
2507 /*guint32 seqlen;*/ /* sequence length */
2509 /* get sequence length, new endianness and boundary for encapsulation */
2510 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2511 stream_is_big_endian, boundary,
2512 &new_stream_is_big_endian, &new_boundary);
2514 /* get element type */
2515 get_CDR_typeCode(tvb, pinfo, tree, offset, new_stream_is_big_endian, new_boundary, header);
2517 /* get length */
2518 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
2519 proto_tree_add_uint(tree, hf_giop_typecode_length, tvb,
2520 *offset-4, 4, u_octet4);
2524 static void dissect_tk_alias_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset,
2525 gboolean stream_is_big_endian, guint32 boundary,
2526 MessageHeader * header) {
2528 guint32 new_boundary; /* new boundary for encapsulation */
2529 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2531 /*guint32 seqlen;*/ /* sequence length */
2533 /* get sequence legnth, new endianness and boundary for encapsulation */
2534 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2535 stream_is_big_endian, boundary,
2536 &new_stream_is_big_endian, &new_boundary);
2538 /* get repository ID */
2539 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2540 hf_giop_repoid);
2542 /* get name */
2543 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2544 hf_giop_typecode_name);
2546 /* get ??? (noname) TypeCode */
2547 get_CDR_typeCode(tvb, pinfo, tree, offset, new_stream_is_big_endian, new_boundary, header);
2552 static void dissect_tk_except_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset,
2553 gboolean stream_is_big_endian, guint32 boundary,
2554 MessageHeader * header) {
2556 guint32 new_boundary; /* new boundary for encapsulation */
2557 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2559 guint32 count; /* parameter count (of tuples) */
2560 /*guint32 seqlen;*/ /* sequence length */
2561 guint32 i; /* loop index */
2563 /* get sequence length, new endianness and boundary for encapsulation */
2564 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2565 stream_is_big_endian, boundary,
2566 &new_stream_is_big_endian, &new_boundary);
2568 /* get repository ID */
2569 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2570 hf_giop_repoid);
2572 /* get name */
2573 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2574 hf_giop_typecode_name);
2576 /* get count of tuples */
2577 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
2578 if (tree) {
2579 proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
2580 *offset-(int)sizeof(count),4,count);
2583 /* get all tuples */
2584 for (i=0; i< count; i++) {
2585 /* get member name */
2586 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2587 hf_giop_typecode_member_name);
2589 /* get member type */
2590 get_CDR_typeCode(tvb, pinfo, tree, offset, new_stream_is_big_endian, new_boundary, header);
2595 static void dissect_tk_value_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset,
2596 gboolean stream_is_big_endian, guint32 boundary,
2597 MessageHeader * header) {
2599 guint32 new_boundary; /* new boundary for encapsulation */
2600 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2602 gint16 s_octet2; /* signed int16 */
2604 guint32 count; /* parameter count (of tuples) */
2605 /*guint32 seqlen;*/ /* sequence length */
2606 guint32 i; /* loop index */
2608 /* get sequence length, new endianness and boundary for encapsulation */
2609 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2610 stream_is_big_endian, boundary,
2611 &new_stream_is_big_endian, &new_boundary);
2613 /* get repository ID */
2614 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2615 hf_giop_repoid);
2617 /* get name */
2618 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2619 hf_giop_typecode_name);
2621 /* get ValueModifier */
2622 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
2623 proto_tree_add_int(tree, hf_giop_typecode_ValueModifier, tvb,
2624 *offset-2, 2, s_octet2);
2626 /* get conrete base */
2627 get_CDR_typeCode(tvb, pinfo, tree, offset, new_stream_is_big_endian, new_boundary,header);
2629 /* get count of tuples */
2630 count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
2631 proto_tree_add_uint(tree, hf_giop_typecode_count, tvb,
2632 *offset-4, 4, count);
2634 /* get all tuples */
2635 for (i=0; i< count; i++) {
2636 /* get member name */
2637 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2638 hf_giop_typecode_member_name);
2640 /* get member type */
2641 get_CDR_typeCode(tvb, pinfo, tree, offset, new_stream_is_big_endian, new_boundary,header);
2643 /* get Visibility */
2644 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
2645 if (tree) {
2646 proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
2647 *offset-(int)sizeof(s_octet2),2,s_octet2);
2654 static void dissect_tk_value_box_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset,
2655 gboolean stream_is_big_endian, guint32 boundary,
2656 MessageHeader * header) {
2658 guint32 new_boundary; /* new boundary for encapsulation */
2659 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2661 /*guint32 seqlen;*/ /* sequence length */
2663 /* get sequence length, new endianness and boundary for encapsulation */
2664 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2665 stream_is_big_endian, boundary,
2666 &new_stream_is_big_endian, &new_boundary);
2668 /* get repository ID */
2669 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2670 hf_giop_repoid);
2672 /* get name */
2673 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2674 hf_giop_typecode_name);
2676 /* get ??? (noname) TypeCode */
2677 get_CDR_typeCode(tvb, pinfo, tree, offset, new_stream_is_big_endian, new_boundary,header);
2681 static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2682 gboolean stream_is_big_endian, guint32 boundary) {
2684 guint32 new_boundary; /* new boundary for encapsulation */
2685 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2687 /*guint32 seqlen;*/ /* sequence length */
2689 /* get sequence length, new endianness and boundary for encapsulation */
2690 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2691 stream_is_big_endian, boundary,
2692 &new_stream_is_big_endian, &new_boundary);
2694 /* get repository ID */
2695 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2696 hf_giop_repoid);
2698 /* get name */
2699 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2700 hf_giop_typecode_name);
2705 static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2706 gboolean stream_is_big_endian, guint32 boundary) {
2708 guint32 new_boundary; /* new boundary for encapsulation */
2709 gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
2711 /*guint32 seqlen;*/ /* sequence length */
2713 /* get sequence length, new endianness and boundary for encapsulation */
2714 /*seqlen = */get_CDR_encap_info(tvb, tree, offset,
2715 stream_is_big_endian, boundary,
2716 &new_stream_is_big_endian, &new_boundary);
2718 /* get repository ID */
2719 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2720 hf_giop_repoid);
2722 /* get name */
2723 dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
2724 hf_giop_typecode_name);
2728 /* Typecode parameter lists are encoded as encapsulations and
2729 * this function gets the encapsulation information; see
2730 * CORBA spec chapter 15
2733 * Renamed to get_CDR_encap_info() for any encapsulation
2734 * we come across, useful helper function
2736 * Also, should return immediately if seqlen == 0.
2737 * ie: Forget about trying to grab endianness for
2738 * zero length sequence.
2740 * Caller must always check seqlen == 0, and not assume its value
2743 * Note: there seemed to be considerable confusion in corba
2744 * circles as to the correct interpretation of encapsulations,
2745 * and zero length sequences etc, but this is our best bet at the
2746 * moment.
2748 * -- FS
2752 guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
2753 gboolean old_stream_is_big_endian, guint32 old_boundary,
2754 gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
2756 guint32 seqlen; /* sequence length */
2757 guint8 giop_endianness;
2759 /* Get sequence length of parameter list */
2760 seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
2761 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
2762 *offset-(int)sizeof(seqlen),4,seqlen);
2765 * seqlen == 0, implies no endianness and no data
2766 * so just return. Populate new_boundary_ptr and
2767 * new_stream_is_big_endian_ptr with current (old)
2768 * values, just to keep everyone happy. -- FS
2771 if (seqlen == 0) {
2773 *new_boundary_ptr = old_boundary;
2774 *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
2775 return seqlen;
2778 /* Start of encapsulation of parameter list */
2779 *new_boundary_ptr = *offset; /* remember */
2780 giop_endianness = get_CDR_octet(tvb,offset);
2782 *new_stream_is_big_endian_ptr = ! giop_endianness;
2785 * Glib: typedef gint gboolean;
2786 * ie: It is not a guint8, so cannot use sizeof to correctly
2787 * highlight octet.
2789 proto_tree_add_uint(tree,hf_giop_endianness,tvb,
2790 *offset-1, 1, giop_endianness);
2792 return seqlen;
2796 * ------------------------------------------------------------------------------------------+
2797 * Public get_CDR_xxx functions.
2798 * ------------------------------------------------------------------------------------------+
2804 * Gets data of type any. This is encoded as a TypeCode
2805 * followed by the encoded value.
2808 void get_CDR_any(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item,
2809 gint *offset, gboolean stream_is_big_endian, int boundary,
2810 MessageHeader * header ) {
2812 guint32 TCKind; /* TypeCode */
2814 /* get TypeCode of any */
2815 TCKind = get_CDR_typeCode(tvb, pinfo, tree, offset, stream_is_big_endian, boundary, header );
2817 /* dissect data of type TCKind */
2818 dissect_data_for_typecode(tvb, pinfo, tree, item, offset, stream_is_big_endian, boundary, header, TCKind );
2822 /* Copy a 1 octet sequence from the tvbuff
2823 * which represents a boolean value, and convert
2824 * it to a boolean value.
2825 * Offset is then incremented by 1, to indicate the 1 octet which
2826 * has been processed.
2829 gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
2830 guint8 val;
2832 val = tvb_get_guint8(tvb, *offset); /* easy */
2833 (*offset)++;
2834 return val;
2837 /* Copy a 1 octet sequence from the tvbuff
2838 * which represents a char, and convert
2839 * it to an char value.
2840 * offset is then incremented by 1, to indicate the 1 octet which
2841 * has been processed.
2844 guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
2845 guint8 val;
2847 val = tvb_get_guint8(tvb, *offset); /* easy */
2848 (*offset)++;
2849 return val;
2855 * Floating Point Data Type double IEEE 754-1985
2857 * Copy an 8 octet sequence from the tvbuff
2858 * which represents a double value, and convert
2859 * it to a double value, taking into account byte order.
2860 * offset is first incremented so that it falls on a proper alignment
2861 * boundary for double values.
2862 * offset is then incremented by 8, to indicate the 8 octets which
2863 * have been processed.
2866 gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2868 gdouble val;
2870 /* double values must be aligned on a 8 byte boundary */
2872 while( ( (*offset + boundary) % 8) != 0)
2873 ++(*offset);
2875 val = (stream_is_big_endian) ? tvb_get_ntohieee_double (tvb, *offset) :
2876 tvb_get_letohieee_double (tvb, *offset);
2878 *offset += 8;
2879 return val;
2884 /* Copy a 4 octet sequence from the tvbuff
2885 * which represents an enum value, and convert
2886 * it to an enum value, taking into account byte order.
2887 * offset is first incremented so that it falls on a proper alignment
2888 * boundary for an enum (4)
2889 * offset is then incremented by 4, to indicate the 4 octets which
2890 * have been processed.
2892 * Enum values are encoded as unsigned long.
2896 guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
2898 return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
2904 * Copy an octet sequence from the tvbuff
2905 * which represents a Fixed point decimal type, and create a string representing
2906 * a Fixed point decimal type. There are no alignment restrictions.
2907 * Size and scale of fixed decimal type is determined by IDL.
2909 * digits - IDL specified number of "digits" for this fixed type
2910 * scale - IDL specified "scale" for this fixed type
2913 * eg: typedef fixed <5,2> fixed_t;
2914 * could represent numbers like 123.45, 789.12,
2917 * As the fixed type could be any size, I will not try to fit it into our
2918 * simple types like gdouble or glong etc. I will just create a string buffer holding
2919 * a representation (after scale is applied), and with a decimal point or zero padding
2920 * inserted at the right place if necessary. The string is null terminated
2922 * so string may look like
2925 * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
2927 * According to spec, digits <= 31
2928 * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
2929 * or <4,0> ?
2932 void get_CDR_fixed(tvbuff_t *tvb, packet_info *pinfo, proto_item *item, gchar **seq,
2933 gint *offset, guint32 digits, gint32 scale) {
2935 guint8 sign; /* 0x0c is positive, 0x0d is negative */
2936 guint32 i ; /* loop */
2937 guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
2938 /* this does not include sign, decimal point and \0 */
2939 guint32 sindex = 0; /* string index */
2940 gchar *tmpbuf; /* temp buff, holds string without scaling */
2941 guint8 tval; /* temp val storage */
2944 * how many bytes to hold digits and scale (if scale <0)
2946 * eg: fixed <5,2> = 5 digits
2947 * fixed <5,-2> = 7 digits (5 + 2 added 0's)
2950 #if DEBUG
2951 printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
2952 #endif
2954 if (scale <0) {
2955 slen = digits - scale; /* allow for digits + padding 0's for negative scal */
2956 } else {
2957 slen = digits; /* digits */
2960 #if DEBUG
2961 printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
2962 #endif
2964 tmpbuf = (gchar *)wmem_alloc0(wmem_packet_scope(), slen); /* allocate temp buffer */
2966 /* If even , grab 1st dig */
2968 if (!(digits & 0x01)) {
2969 tval = get_CDR_octet(tvb,offset);
2970 #if DEBUG
2971 printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
2972 #endif
2973 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
2974 sindex++;
2978 * Loop, but stop BEFORE we hit last digit and sign
2979 * if digits = 1 or 2, then this part is skipped
2982 if (digits>2) {
2983 for(i=0; i< ((digits-1)/2 ); i++) {
2984 tval = get_CDR_octet(tvb,offset);
2985 #if DEBUG
2986 printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
2987 #endif
2989 tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
2990 sindex++;
2991 tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
2992 sindex++;
2995 } /* digits > 3 */
2997 #if DEBUG
2998 printf("giop:get_CDR_fixed(): before last digit \n");
2999 #endif
3002 /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
3004 tval = get_CDR_octet(tvb,offset);
3005 #if DEBUG
3006 printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
3007 #endif
3008 tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
3009 sindex++;
3011 sign = tval & 0x0f; /* get sign */
3013 /* So now, we have all digits in an array, and the sign byte
3014 * so lets generate a printable string, taking into account the scale
3015 * and sign values.
3018 sindex = 0; /* reset */
3019 *seq = wmem_alloc0_array(wmem_packet_scope(), gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
3020 * \0 -- TODO check slen is reasonable first */
3021 #if DEBUG
3022 printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
3023 #endif
3025 switch(sign) {
3026 case 0x0c:
3027 (*seq)[sindex] = '+'; /* put sign in first string position */
3028 break;
3029 case 0x0d:
3030 (*seq)[sindex] = '-';
3031 break;
3032 default:
3033 expert_add_info_format(pinfo, item, &ei_giop_unknown_sign_value,
3034 "Unknown sign value in fixed type %u", sign);
3035 (*seq)[sindex] = '*'; /* flag as sign unknown */
3036 break;
3039 sindex++;
3041 /* Add decimal point or padding 0's, depending if scale is positive or
3042 * negative, respectively
3045 if (scale>0) {
3046 for (i=0; i<digits-scale; i++) {
3047 (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
3048 sindex++;
3051 (*seq)[sindex] = '.'; /* decimal point */
3052 sindex++;
3054 for (i=digits-scale; i<digits; i++) {
3055 (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
3056 sindex++;
3059 (*seq)[sindex] = '\0'; /* string terminator */
3061 } else {
3063 /* negative scale, dump digits and pad out with 0's */
3065 for (i=0; i<digits-scale; i++) {
3066 if (i<digits) {
3067 (*seq)[sindex] = tmpbuf[i]; /* save digits */
3068 } else {
3069 (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
3071 sindex++;
3074 (*seq)[sindex] = '\0'; /* string terminator */
3078 #if DEBUG
3079 printf("giop:get_CDR_fixed(): value = %s \n", *seq);
3080 #endif
3082 return;
3089 * Floating Point Data Type float IEEE 754-1985
3091 * Copy an 4 octet sequence from the tvbuff
3092 * which represents a float value, and convert
3093 * it to a float value, taking into account byte order.
3094 * offset is first incremented so that it falls on a proper alignment
3095 * boundary for float values.
3096 * offset is then incremented by 4, to indicate the 4 octets which
3097 * have been processed.
3100 gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
3102 gfloat val;
3104 /* float values must be aligned on a 4 byte boundary */
3106 while( ( (*offset + boundary) % 4) != 0)
3107 ++(*offset);
3109 val = (stream_is_big_endian) ? tvb_get_ntohieee_float (tvb, *offset) :
3110 tvb_get_letohieee_float (tvb, *offset);
3112 *offset += 4;
3113 return val;
3119 * Decode an Interface type, and display it on the tree.
3122 void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
3123 gboolean stream_is_big_endian, int boundary) {
3126 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
3128 return;
3132 /* Copy a 4 octet sequence from the tvbuff
3133 * which represents a signed long value, and convert
3134 * it to an signed long vaule, taking into account byte order.
3135 * offset is first incremented so that it falls on a proper alignment
3136 * boundary for long values.
3137 * offset is then incremented by 4, to indicate the 4 octets which
3138 * have been processed.
3141 gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
3143 gint32 val;
3145 /* unsigned long values must be aligned on a 4 byte boundary */
3146 while( ( (*offset + boundary) % 4) != 0)
3147 ++(*offset);
3149 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
3150 tvb_get_letohl (tvb, *offset);
3152 *offset += 4;
3153 return val;
3156 /* Copy a 8 octet sequence from the tvbuff
3157 * which represents a signed long long value, and convert
3158 * it to an signed long long vaule, taking into account byte order.
3159 * offset is first incremented so that it falls on a proper alignment
3160 * boundary for long long values.
3161 * offset is then incremented by 8, to indicate the 8 octets which
3162 * have been processed.
3165 gint64 get_CDR_long_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
3167 gint64 val;
3169 /* unsigned long long values must be aligned on a 8 byte boundary */
3170 while( ( (*offset + boundary) % 8) != 0)
3171 ++(*offset);
3173 val = (stream_is_big_endian) ? tvb_get_ntoh64 (tvb, *offset) :
3174 tvb_get_letoh64 (tvb, *offset);
3176 *offset += 8;
3177 return val;
3181 * Decode an Object type, and display it on the tree.
3184 void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
3185 gboolean stream_is_big_endian, int boundary) {
3187 decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
3189 return;
3193 /* Copy a 1 octet sequence from the tvbuff
3194 * which represents a octet, and convert
3195 * it to an octet value.
3196 * offset is then incremented by 1, to indicate the 1 octet which
3197 * has been processed.
3200 guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
3201 guint8 val;
3203 val = tvb_get_guint8(tvb, *offset); /* easy */
3204 (*offset)++;
3205 return val;
3209 /* Copy a sequence of octets from the tvbuff.
3210 * Memory is allocated in packet pool and will be
3211 * automatically freed once the packet dissection is finished.
3212 * This function also increments offset by len.
3215 void get_CDR_octet_seq(tvbuff_t *tvb, const gchar **seq, int *offset, guint32 len) {
3216 guint8 *seq_buf;
3219 * Make sure that the entire sequence of octets is in the buffer before
3220 * allocating the buffer, so that we don't try to allocate a buffer bigger
3221 * than the data we'll actually be copying, and thus don't run the risk
3222 * of crashing if the buffer is *so* big that we fail to allocate it
3223 * and "wmem_alloc0_array()" aborts.
3225 tvb_ensure_bytes_exist(tvb, *offset, len);
3228 * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
3229 * do what we do now, and null-terminate the string (which also means
3230 * we don't need to zero out the entire allocation, just the last byte)?
3232 seq_buf = wmem_alloc0_array(wmem_packet_scope(), gchar, len + 1);
3233 tvb_memcpy( tvb, seq_buf, *offset, len);
3234 *seq = seq_buf;
3235 *offset += len;
3239 /* Copy a 2 octet sequence from the tvbuff
3240 * which represents a signed short value, and convert
3241 * it to a signed short value, taking into account byte order.
3242 * offset is first incremented so that it falls on a proper alignment
3243 * boundary for short values.
3244 * offset is then incremented by 2, to indicate the 2 octets which
3245 * have been processed.
3248 gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
3250 gint16 val;
3252 /* short values must be aligned on a 2 byte boundary */
3253 while( ( (*offset + boundary) % 2) != 0)
3254 ++(*offset);
3256 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
3257 tvb_get_letohs (tvb, *offset);
3259 *offset += 2;
3260 return val;
3264 /* Add an octet string to the tree. This function exists in an attempt
3265 * to eliminate function-local variables in packet-parlay.c .
3267 void
3268 giop_add_CDR_string(proto_tree *tree, tvbuff_t *tvb, int *offset,
3269 gboolean stream_is_big_endian, int boundary, int hf)
3271 guint32 u_octet4;
3272 const gchar *seq = NULL;
3274 u_octet4 = get_CDR_string(tvb, &seq, offset, stream_is_big_endian, boundary);
3275 proto_tree_add_string(tree, hf, tvb, *offset-u_octet4, u_octet4, (u_octet4 > 0) ? seq : "");
3279 /* Copy an octet sequence from the tvbuff
3280 * which represents a string, and convert
3281 * it to an string value, taking into account byte order.
3282 * offset is first incremented so that it falls on a proper alignment
3283 * boundary for string values. (begins with an unsigned long LI)
3285 * String sequence is copied to a buffer "seq".
3286 * Memory is allocated in packet pool and will be
3287 * automatically freed once the packet dissection is finished.
3288 * offset is then incremented, to indicate the octets which
3289 * have been processed.
3291 * returns number of octets in the sequence
3293 * Note: This function only supports single byte encoding at the
3294 * moment until I get a handle on multibyte encoding etc.
3299 guint32 get_CDR_string(tvbuff_t *tvb, const gchar **seq, int *offset, gboolean stream_is_big_endian,
3300 int boundary ) {
3302 guint32 slength;
3303 gint reported_length;
3305 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
3307 #if 0
3308 (*offset)++; /* must step past \0 delimiter */
3309 #endif
3311 reported_length = tvb_reported_length_remaining(tvb, *offset-4);
3312 if (slength > (guint32)reported_length) {
3313 /* Size exceeds packet size, so just grab the rest of the packet */
3314 /* XXX - add expert_add_info_format note */
3315 get_CDR_octet_seq(tvb, seq, offset, reported_length);
3316 return reported_length;
3318 else if (slength > 0) {
3319 get_CDR_octet_seq(tvb, seq, offset, slength);
3320 } else {
3321 *seq = wmem_strdup(wmem_packet_scope(), ""); /* zero-length string */
3324 return slength; /* return length */
3328 /* Process a sequence of octets that represent the
3329 * Pseudo Object Type "TypeCode". Typecodes are used for example,
3330 * by "Any values".
3331 * This function also increments offset to the correct position.
3333 * It will parse the TypeCode and output data to the "tree" provided
3334 * by the user
3336 * It returns a guint32 representing a TCKind value.
3339 guint32 get_CDR_typeCode(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree,
3340 gint *offset, gboolean stream_is_big_endian,
3341 int boundary, MessageHeader * header ) {
3342 guint32 val;
3344 gint16 s_octet2; /* signed int16 */
3345 guint16 u_octet2; /* unsigned int16 */
3346 guint32 u_octet4; /* unsigned int32 */
3347 proto_item *ti;
3349 val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
3350 ti = proto_tree_add_uint(tree,hf_giop_TCKind, tvb, *offset-4, 4, val);
3352 /* Grab the data according to Typecode Table - Corba Chapter 15 */
3354 switch (val) {
3355 case tk_null: /* empty parameter list */
3356 break;
3357 case tk_void: /* empty parameter list */
3358 break;
3359 case tk_short: /* empty parameter list */
3360 break;
3361 case tk_long: /* empty parameter list */
3362 break;
3363 case tk_ushort: /* empty parameter list */
3364 break;
3365 case tk_ulong: /* empty parameter list */
3366 break;
3367 case tk_float: /* empty parameter list */
3368 break;
3369 case tk_double: /* empty parameter list */
3370 break;
3371 case tk_boolean: /* empty parameter list */
3372 break;
3373 case tk_char: /* empty parameter list */
3374 break;
3375 case tk_octet: /* empty parameter list */
3376 break;
3377 case tk_any: /* empty parameter list */
3378 break;
3379 case tk_TypeCode: /* empty parameter list */
3380 break;
3381 case tk_Principal: /* empty parameter list */
3382 break;
3383 case tk_objref: /* complex parameter list */
3384 dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary);
3385 break;
3386 case tk_struct: /* complex parameter list */
3387 dissect_tk_struct_params(tvb, pinfo, tree, offset, stream_is_big_endian, boundary, header );
3388 break;
3389 case tk_union: /* complex parameter list */
3390 dissect_tk_union_params(tvb, pinfo, tree, ti, offset, stream_is_big_endian, boundary, header );
3391 break;
3392 case tk_enum: /* complex parameter list */
3393 dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary);
3394 break;
3396 case tk_string: /* simple parameter list */
3397 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
3398 if (tree) {
3399 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
3400 *offset-(int)sizeof(u_octet4),4,u_octet4);
3402 break;
3404 case tk_sequence: /* complex parameter list */
3405 dissect_tk_sequence_params(tvb, pinfo, tree, offset, stream_is_big_endian, boundary, header );
3406 break;
3407 case tk_array: /* complex parameter list */
3408 dissect_tk_array_params(tvb, pinfo, tree, offset, stream_is_big_endian, boundary, header );
3409 break;
3410 case tk_alias: /* complex parameter list */
3411 dissect_tk_alias_params(tvb, pinfo, tree, offset, stream_is_big_endian, boundary, header );
3412 break;
3413 case tk_except: /* complex parameter list */
3414 dissect_tk_except_params(tvb, pinfo, tree, offset, stream_is_big_endian, boundary, header );
3415 break;
3416 case tk_longlong: /* empty parameter list */
3417 break;
3418 case tk_ulonglong: /* empty parameter list */
3419 break;
3420 case tk_longdouble: /* empty parameter list */
3421 break;
3422 case tk_wchar: /* empty parameter list */
3423 break;
3424 case tk_wstring: /* simple parameter list */
3425 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
3426 if (tree) {
3427 proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
3428 *offset-(int)sizeof(u_octet4),4,u_octet4);
3430 break;
3432 case tk_fixed: /* simple parameter list */
3433 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
3434 if (tree) {
3435 proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
3436 *offset-(int)sizeof(u_octet2),2,u_octet2);
3439 s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
3440 if (tree) {
3441 proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
3442 *offset-(int)sizeof(s_octet2),2,s_octet2);
3444 break;
3446 case tk_value: /* complex parameter list */
3447 dissect_tk_value_params(tvb, pinfo, tree, offset, stream_is_big_endian, boundary, header );
3448 break;
3449 case tk_value_box: /* complex parameter list */
3450 dissect_tk_value_box_params(tvb, pinfo, tree, offset, stream_is_big_endian, boundary, header );
3451 break;
3452 case tk_native: /* complex parameter list */
3453 dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary);
3454 break;
3455 case tk_abstract_interface: /* complex parameter list */
3456 dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary );
3457 break;
3458 default:
3459 expert_add_info_format(pinfo, ti, &ei_giop_unknown_tckind, "Unknown TCKind %u", val);
3460 break;
3461 } /* val */
3463 return val;
3468 /* Copy a 4 octet sequence from the tvbuff
3469 * which represents an unsigned long value, and convert
3470 * it to an unsigned long value, taking into account byte order.
3471 * offset is first incremented so that it falls on a proper alignment
3472 * boundary for unsigned long values.
3473 * offset is then incremented by 4, to indicate the 4 octets which
3474 * have been processed.
3477 guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
3479 guint32 val;
3481 /* unsigned long values must be aligned on a 4 byte boundary */
3482 while( ( (*offset + boundary) % 4) != 0)
3483 ++(*offset);
3485 val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
3486 tvb_get_letohl (tvb, *offset);
3488 *offset += 4;
3489 return val;
3492 /* Copy a 8 octet sequence from the tvbuff
3493 * which represents an unsigned long long value, and convert
3494 * it to an unsigned long long vaule, taking into account byte order.
3495 * offset is first incremented so that it falls on a proper alignment
3496 * boundary for unsigned long long values.
3497 * offset is then incremented by 4, to indicate the 4 octets which
3498 * have been processed.
3501 guint64 get_CDR_ulong_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
3503 guint64 val;
3505 /* unsigned long long values must be aligned on a 8 byte boundary */
3506 while( ( (*offset + boundary) % 8) != 0)
3507 ++(*offset);
3509 val = (stream_is_big_endian) ? tvb_get_ntoh64 (tvb, *offset) :
3510 tvb_get_letoh64 (tvb, *offset);
3512 *offset += 8;
3513 return val;
3516 /* Copy a 2 octet sequence from the tvbuff
3517 * which represents an unsigned short value, and convert
3518 * it to an unsigned short value, taking into account byte order.
3519 * offset is first incremented so that it falls on a proper alignment
3520 * boundary for unsigned short values.
3521 * offset is then incremented by 2, to indicate the 2 octets which
3522 * have been processed.
3525 guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
3527 guint16 val;
3529 /* unsigned short values must be aligned on a 2 byte boundary */
3530 while( ( (*offset + boundary) % 2) != 0)
3531 ++(*offset);
3533 val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
3534 tvb_get_letohs (tvb, *offset);
3536 *offset += 2;
3537 return val;
3542 /* Copy a wchar from the tvbuff.
3543 * Memory is allocated in packet pool and will be
3544 * automatically freed once the packet dissection is finished.
3545 * This function also increments offset according to
3546 * the wchar size.
3548 * For GIOP 1.1 read 2 octets and return size -2. The
3549 * negation means there is no size element in the packet
3550 * and therefore no size to add to the tree.
3552 * For GIOP 1.2 read size of wchar and the size
3553 * octets. size is returned as a gint8.
3555 * For both GIOP versions the wchar is returned
3556 * as a printable string.
3560 /* NOTE: This is very primitive in that it just reads
3561 * the wchar as a series of octets and returns them
3562 * to the user. No translation is attempted based on
3563 * byte orientation, nor on code set. I.e it only
3564 * really reads past the wchar and sets the offset
3565 * correctly.
3568 /* The "decoding" is done according to CORBA chapter 15.
3569 * Wchar is not supported for GIOP 1.0.
3572 gint get_CDR_wchar(tvbuff_t *tvb, const gchar **seq, int *offset, MessageHeader * header) {
3574 gint slength;
3575 const gchar *raw_wstring;
3577 /* CORBA chapter 15:
3578 * - prior to GIOP 1.2 wchar limited to two octet fixed length.
3579 * - GIOP 1.2 wchar is encoded as an unsigned binary octet
3580 * followed by the elements of the octet sequence representing
3581 * the encoded value of the wchar.
3584 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
3585 slength = 2; /* set for GIOP 1.1 length in octets */
3587 if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
3588 slength = get_CDR_octet(tvb,offset);
3590 if (slength > 0) {
3591 /* ??? assume alignment is ok for GIOP 1.1 ??? */
3592 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
3594 /* now turn octets (wchar) into something that can be printed by the user */
3595 *seq = make_printable_string(raw_wstring, slength);
3598 /* if GIOP 1.1 negate length to indicate not an item to add to tree */
3599 if (header->GIOP_version.minor < 2)
3600 slength = -slength;
3602 return slength; /* return length */
3607 /* Copy a wstring from the tvbuff.
3608 * Memory is allocated in packet pool and will be
3609 * automatically freed once the packet dissection is finished.
3610 * This function also increments offset, according to
3611 * wstring length. length is returned as guint32
3614 /* NOTE: This is very primitive in that it just reads
3615 * the wstring as a series of octets and returns them
3616 * to the user. No translation is attempted based on
3617 * byte orientation, nor on code set. I.e it only
3618 * really reads past the wstring and sets the offset
3619 * correctly.
3622 /* The "decoding" is done according to CORBA chapter 15.
3623 * Wstring is not supported for GIOP 1.0.
3627 guint32 get_CDR_wstring(tvbuff_t *tvb, const gchar **seq, int *offset, gboolean stream_is_big_endian,
3628 int boundary, MessageHeader * header) {
3630 guint32 slength;
3631 gint reported_length;
3632 const gchar *raw_wstring;
3634 /* CORBA chapter 15:
3635 * - prior to GIOP 1.2 wstring limited to two octet fixed length.
3636 * length and string are NUL terminated (length???).
3637 * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
3638 * terminated.
3641 *seq = NULL; /* set in case GIOP 1.2 length is 0 */
3643 /* get length, same for all GIOP versions,
3644 * although for 1.2 CORBA doesnt say, so assume.
3646 slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
3648 #ifdef DEBUG
3649 if (slength>200) {
3650 fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
3651 slength = 5; /* better than core dumping during debug */
3653 #endif
3655 if (header->GIOP_version.minor < 2) {
3656 #if 0
3657 (*offset)++; /* must step past \0 delimiter */
3658 #endif
3659 /* assume length is number of characters and not octets, spec not clear */
3660 slength = slength * 2; /* length in octets is 2 * wstring length */
3663 reported_length = tvb_reported_length_remaining(tvb, *offset-4);
3664 if (slength > (guint32)reported_length) {
3665 slength = reported_length;
3666 /* XXX - add expert_add_info_format note */
3669 if (slength > 0) {
3670 get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
3672 /* now turn octets (wstring) into something that can be printed by the user */
3673 *seq = make_printable_string(raw_wstring, slength);
3676 return slength; /* return length */
3681 * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
3682 * GIOP 1.2
3683 * typedef short AddressingDisposition;
3684 * const short KeyAddr = 0;
3685 * const short ProfileAddr = 1;
3686 * const short ReferenceAddr = 2;
3687 * struct IORAddressingInfo {
3688 * unsigned long selected_profile_index;
3689 * IOP::IOR ior;
3690 * };
3692 * union TargetAddress switch (AddressingDisposition) {
3693 * case KeyAddr: sequence <octet> object_key;
3694 * case ProfileAddr: IOP::TaggedProfile profile;
3695 * case ReferenceAddr: IORAddressingInfo ior;
3696 * };
3699 static void
3700 dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
3701 gboolean stream_is_big_endian, guint32 *object_key_len,
3702 const gchar **object_key_val)
3704 guint16 discriminant;
3705 const gchar *object_key = NULL;
3706 guint32 len = 0;
3707 guint32 u_octet4;
3708 proto_item* ti;
3710 discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3711 proto_tree_add_uint (tree, hf_giop_target_address_discriminant, tvb, *offset -2, 2, discriminant);
3713 switch (discriminant)
3715 case 0: /* KeyAddr */
3716 len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3717 ti = proto_tree_add_uint (tree, hf_giop_target_address_key_addr_len, tvb, *offset -4, 4, len);
3719 if (len > (guint32)tvb_reported_length_remaining(tvb, *offset-4)) {
3720 expert_add_info_format(pinfo, ti, &ei_giop_length_too_big, "KeyAddr key length bigger than packet size");
3721 return;
3724 if (len > 0) {
3726 get_CDR_octet_seq(tvb, &object_key, offset, len);
3728 proto_tree_add_string(tree, hf_giop_target_address_key_addr, tvb, *offset - len,
3729 len, make_printable_string( object_key, len ));
3731 if (object_key_len) {
3732 *object_key_len = len;
3734 if (object_key_val) {
3735 *object_key_val = object_key;
3738 break;
3739 case 1: /* ProfileAddr */
3740 decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
3741 stream_is_big_endian, NULL);
3742 break;
3743 case 2: /* ReferenceAddr */
3744 u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3745 proto_tree_add_uint (tree, hf_giop_target_address_ref_addr_len, tvb, *offset -4, 4, u_octet4);
3747 decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
3748 break;
3749 default:
3750 break;
3753 static void decode_CodeSets(tvbuff_t *tvb, proto_tree *tree, int *offset,
3754 gboolean stream_is_be, guint32 boundary) {
3756 /* The boundary being passed in is the offset where the context_data
3757 * sequence begins. */
3759 guint32 code_set_id;
3760 if(tree) {
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);
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);
3775 * From Section 2.7.3 of the Real-time CORBA 1.1 Standard, the CORBA priority
3776 * is represented in the GIOP service request as:
3778 * module IOP {
3779 * typedef short ServiceId;
3780 * const ServiceId RTCorbaPriority = 10;
3781 * };
3783 * The RT-CORBA priority is a CDR encoded short value in a sequence<octet>
3784 * buffer.
3786 static void decode_RTCorbaPriority(tvbuff_t *tvb, proto_tree *tree, int *offset,
3787 gboolean stream_is_be, guint32 boundary) {
3789 /* The boundary being passed in is the offset where the context_data
3790 * sequence begins. */
3792 gint16 rtpriority;
3794 /* RTCorbaPriority is stored as a CDR encoded short */
3795 /* We pass in -boundary, because the alignment is calculated relative to
3796 the beginning of the context_data sequence.
3797 Inside get_CDR_short(), the calculation will be (offset + (- boundary)) % 2
3798 to determine the correct alignment of the short. */
3799 rtpriority = get_CDR_short(tvb, offset, stream_is_be, -((gint32) boundary) );
3801 /* Highlight all of context_data except for the first endian byte */
3802 proto_tree_add_uint(tree, hf_giop_rt_corba_priority, tvb, *offset - 2, 2, rtpriority);
3805 static void decode_UnknownServiceContext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
3806 gboolean stream_is_be, guint32 boundary) {
3808 guint32 context_data_len;
3809 const gchar *context_data;
3810 proto_item *ti;
3812 /* get sequence length, and NO encapsulation */
3813 context_data_len = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
3814 ti = proto_tree_add_uint(tree, hf_giop_context_data_len, tvb, *offset - 4, 4, context_data_len);
3816 if (context_data_len > (guint32)tvb_reported_length_remaining(tvb, *offset-4)) {
3817 expert_add_info_format(pinfo, ti, &ei_giop_length_too_big, "Context data length bigger than packet size");
3818 return;
3821 /* return if zero length sequence */
3822 if(context_data_len == 0)
3823 return;
3826 * Now decode sequence according to vendor ServiceId, but I dont
3827 * have that yet, so just dump it as data.
3830 /* fetch all octets in this sequence */
3832 get_CDR_octet_seq(tvb, &context_data, offset, context_data_len);
3834 /* Make a printable string */
3835 proto_tree_add_string(tree, hf_giop_context_data, tvb, *offset - context_data_len ,
3836 context_data_len, make_printable_string( context_data, context_data_len));
3840 * Corba , chp 13.7
3844 * typedef unsigned long ServiceID;
3846 * struct ServiceContext {
3847 * ServiceID context_id;
3848 * sequence <octet> context_data;
3849 * };
3850 * typedef sequence <ServiceContext> ServiceContextList;
3853 * Note: Spec says context_data is an encapsulation.
3858 static void decode_ServiceContextList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
3859 gboolean stream_is_be, guint32 boundary) {
3861 guint32 seqlen; /* sequence length */
3862 guint32 context_data_len; /* context data sequence length */
3864 proto_tree *tree = NULL; /* ServiceContext tree */
3865 proto_tree *sub_tree1 = NULL;
3866 proto_item *tf = NULL, *tf_st1;
3868 guint32 context_id;
3870 guint32 i;
3871 guint32 vscid; /* Vendor Service context id */
3872 guint32 scid;
3873 gboolean encapsulation_is_be;
3874 guint32 encapsulation_boundary;
3875 int temp_offset;
3876 int start_offset = *offset;
3878 /* create a subtree */
3880 /* set length to 0 now and correct with proto_item_set_len() later */
3881 tf = proto_tree_add_text (ptree, tvb, *offset, 0, "ServiceContextList");
3882 tree = proto_item_add_subtree (tf, ett_giop_scl);
3884 /* Get sequence length (number of elements) */
3885 seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
3886 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
3887 *offset-(int)sizeof(seqlen),4,seqlen);
3889 /* return if zero length sequence */
3891 if (seqlen == 0) {
3892 if (tf) {
3893 if (*offset - start_offset <= 0)
3894 THROW(ReportedBoundsError);
3895 proto_item_set_len(tf, *offset - start_offset);
3898 return;
3901 /* Loop for all ServiceContext's */
3903 for (i=0; i<seqlen; i++) {
3905 context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
3906 vscid = (context_id & 0xffffff00) >> 8; /* vendor info, top 24 bits */
3907 scid = context_id & 0x000000ff; /* standard service info, lower 8 bits */
3909 tf_st1 = proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
3910 *offset-4, 4, vscid);
3912 proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
3913 *offset-4, 4, scid);
3915 temp_offset = *offset;
3916 /* The OMG has vscid of 0 reserved */
3917 if( vscid != 0 || scid > max_service_context_id ) {
3918 decode_UnknownServiceContext(tvb, pinfo, tree, offset, stream_is_be, boundary);
3919 continue;
3922 /* get sequence length, new endianness and boundary for encapsulation */
3923 context_data_len = get_CDR_encap_info(tvb, sub_tree1, offset,
3924 stream_is_be, boundary,
3925 &encapsulation_is_be , &encapsulation_boundary);
3927 proto_item_set_len(tf_st1, 8 + context_data_len);
3928 sub_tree1 = proto_item_add_subtree (tf_st1, ett_giop_scl_st1);
3930 if (context_data_len == 0)
3931 continue;
3933 /* See CORBA 3.0.2 standard, section Section 15.3.3 "Encapsulation",
3934 * for how CDR types can be marshalled into a sequence<octet>.
3935 * The first octet in the sequence determines endian order,
3936 * 0 == big-endian, 1 == little-endian
3939 switch(scid)
3941 case 0x01: /* Codesets */
3942 decode_CodeSets(tvb, sub_tree1, offset,
3943 encapsulation_is_be, encapsulation_boundary);
3944 break;
3945 case 0x0a: /* RTCorbaPriority */
3946 decode_RTCorbaPriority(tvb, sub_tree1, offset,
3947 encapsulation_is_be, encapsulation_boundary);
3948 break;
3949 default:
3951 /* Need to fill these in as we learn them */
3952 *offset = temp_offset;
3953 decode_UnknownServiceContext(tvb, pinfo, sub_tree1, offset, stream_is_be,
3954 boundary);
3955 break;
3957 /* Set the offset to the end of the context_data sequence */
3958 *offset = temp_offset + 4 + context_data_len;
3960 } /* for seqlen */
3962 proto_item_set_len(tf, *offset - start_offset);
3965 static void
3966 dissect_reply_body (tvbuff_t *tvb, guint offset, packet_info *pinfo,
3967 proto_tree *tree, gboolean stream_is_big_endian,
3968 guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
3970 guint sequence_length;
3971 gboolean exres = FALSE; /* result of trying explicit dissectors */
3972 gint reply_body_length;
3975 * comp_req_list stuff
3978 comp_req_list_entry_t * entry = NULL; /* data element in our list */
3980 guint32 mfn;
3982 switch (reply_status)
3984 case SYSTEM_EXCEPTION:
3986 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
3987 break;
3989 case USER_EXCEPTION:
3991 sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
3992 proto_tree_add_uint(tree, hf_giop_exception_len, tvb, offset-4, 4,
3993 sequence_length);
3995 if (sequence_length != 0 && sequence_length < ITEM_LABEL_LENGTH)
3997 header->exception_id = tvb_get_stringz(wmem_packet_scope(), tvb,offset, &sequence_length);
3999 proto_tree_add_string(tree, hf_giop_exception_id, tvb, offset,
4000 sequence_length, header->exception_id);
4001 offset += sequence_length;
4005 * Now just fall through to the NO_EXCEPTION part
4006 * as this is common .
4011 case NO_EXCEPTION:
4014 /* lookup MFN in hash directly */
4016 mfn = get_mfn_from_fn(pinfo->fd->num);
4018 if (mfn == pinfo->fd->num)
4019 return; /* no matching frame number, what am I */
4021 /* get entry for this MFN */
4022 entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
4024 if (!entry)
4025 return; /* no matching entry */
4029 * If this packet is a REPLY to a RESOLVE(request)
4030 * then decode IOR.
4031 * TODO - make this lookup faster -- FS
4034 if (!strcmp(giop_op_resolve,entry->operation)) {
4035 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
4036 return; /* done */
4039 /* TODO -- Put stuff here for other "interesting operations" */
4043 * Call sub dissector.
4044 * First try an find a explicit sub_dissector, then if that
4045 * fails, try the heuristic method.
4049 if(entry->repoid) {
4050 exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
4053 /* Only call heuristic if no explicit dissector was found */
4055 if(! exres) {
4056 exres = try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
4059 if (!exres && !strcmp(giop_op_is_a, entry->operation) && tree) {
4060 proto_tree_add_text(tree, tvb, offset - 1, 1, "Type Id%s matched",
4061 get_CDR_boolean(tvb, &offset) ? "" : " not");
4064 if(! exres) {
4065 gint stub_length = tvb_reported_length_remaining(tvb, offset);
4066 if (stub_length >0)
4067 proto_tree_add_item(tree, hf_giop_stub_data, tvb,
4068 offset, stub_length, ENC_NA);
4071 break;
4073 case LOCATION_FORWARD:
4074 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
4076 break;
4078 case LOCATION_FORWARD_PERM:
4079 decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
4081 break;
4083 case NEEDS_ADDRESSING_MODE: {
4084 guint16 addr_disp;
4085 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
4086 proto_tree_add_uint (tree, hf_giop_address_disp, tvb, offset-2, 2, addr_disp);
4087 break;
4090 default:
4091 reply_body_length = tvb_reported_length_remaining(tvb, offset);
4092 if (reply_body_length >0)
4093 proto_tree_add_item(tree, hf_giop_reply_body, tvb,
4094 offset, reply_body_length, ENC_NA);
4095 break;
4104 /* The format of the Reply Header for GIOP 1.0 and 1.1
4105 * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
4107 struct ReplyHeader_1_0 {
4108 IOP::ServiceContextList service_context;
4109 unsigned long request_id;
4110 ReplyStatusType_1_0 reply_status;
4114 static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
4115 MessageHeader * header,
4116 gboolean stream_is_big_endian) {
4118 guint32 offset = 0;
4119 guint32 request_id;
4120 guint32 reply_status;
4121 proto_tree *reply_tree;
4122 proto_item *tf;
4123 guint32 mfn; /* matching frame number */
4125 tf = proto_tree_add_text (tree, tvb, offset, -1, "General Inter-ORB Protocol Reply");
4126 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
4129 * Decode IOP::ServiceContextList
4132 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
4134 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4136 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id );
4138 proto_tree_add_uint(reply_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
4140 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4141 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
4142 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
4143 proto_tree_add_uint(reply_tree, hf_giop_reply_status, tvb,
4144 offset-4, 4, reply_status);
4147 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
4150 if (! pinfo->fd->flags.visited) {
4151 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
4152 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
4153 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
4157 header->req_id = request_id; /* save for sub dissector */
4158 header->rep_status = reply_status; /* save for sub dissector */
4160 /* Do we have a body */
4161 if (tvb_reported_length_remaining(tvb, offset) > 0)
4162 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
4163 reply_status, header,tree);
4166 /** The format of the GIOP 1.2 Reply header is very similar to the 1.0
4167 * and 1.1 header, only the fields have been rearranged. From Section
4168 * 15.4.3.1 of the CORBA 2.4 specification:
4170 * struct ReplyHeader_1_2 {
4171 * unsigned long request_id;
4172 * ReplyStatusType_1_2 reply_status;
4173 * IOP:ServiceContextList service_context;
4174 * };
4177 static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
4178 proto_tree * tree,
4179 MessageHeader * header,
4180 gboolean stream_is_big_endian) {
4182 guint offset = 0;
4183 guint32 request_id;
4184 guint32 reply_status;
4185 proto_tree *reply_tree;
4186 proto_item *tf;
4187 guint32 mfn; /* matching frame number */
4189 tf = proto_tree_add_text (tree, tvb, offset, -1, "General Inter-ORB Protocol Reply");
4190 reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
4192 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4193 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
4194 proto_tree_add_uint (reply_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
4196 reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4197 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
4198 val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
4199 proto_tree_add_uint(reply_tree, hf_giop_reply_status, tvb,
4200 offset-4, 4, reply_status);
4203 * Decode IOP::ServiceContextList
4206 decode_ServiceContextList(tvb, pinfo, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
4209 * GIOP 1.2 Reply body must fall on an 8 octet alignment.
4212 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
4215 * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
4218 if (! pinfo->fd->flags.visited) {
4219 mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
4220 if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
4221 insert_in_complete_reply_hash(pinfo->fd->num, mfn);
4226 * Add header to argument list so sub dissector can get header info.
4229 header->req_id = request_id; /* save for sub dissector */
4230 header->rep_status = reply_status; /* save for sub dissector */
4232 dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
4233 reply_status,header,tree);
4236 static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
4237 proto_tree * tree,
4238 gboolean stream_is_big_endian) {
4240 guint offset = 0;
4241 guint32 request_id;
4242 proto_tree *cancel_request_tree;
4243 proto_item *tf;
4245 tf = proto_tree_add_text (tree, tvb, offset, -1, "General Inter-ORB Protocol CancelRequest");
4246 cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
4248 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4249 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
4250 proto_tree_add_uint (cancel_request_tree,hf_giop_req_id, tvb, offset-4, 4, request_id);
4253 /** The formats for GIOP 1.0 and 1.1 Request messages are defined
4254 * in section 15.4.2.1 of the CORBA 2.4 specification.
4256 * struct RequestHeader{
4257 * IOP::ServiceContextList service_context;
4258 * unsigned long request_id;
4259 * boolean response_expected;
4260 * octet reserved[3]; // Only in GIOP 1.1
4261 * sequence<octet> object_key;
4262 * string operation;
4263 * CORBA::OctetSeq requesting_principal;
4266 static void
4267 dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
4268 proto_tree * tree,
4269 MessageHeader * header, gboolean stream_is_big_endian)
4271 guint32 offset = 0;
4272 guint32 request_id;
4273 guint32 len = 0;
4275 guint32 objkey_len = 0; /* object key length */
4276 const gchar *objkey = NULL; /* object key sequence */
4277 gboolean exres = FALSE; /* result of trying explicit dissectors */
4279 const gchar *operation;
4280 const gchar *requesting_principal;
4281 guint8 response_expected;
4282 const gchar *reserved;
4283 gchar miop[4];
4284 proto_tree *request_tree;
4285 proto_item *tf;
4287 gchar *repoid = NULL; /* from object key lookup in objkey hash */
4289 tf = proto_tree_add_text (tree, tvb, offset, -1, "General Inter-ORB Protocol Request");
4290 request_tree = proto_item_add_subtree (tf, ett_giop_request);
4293 * Decode IOP::ServiceContextList
4296 decode_ServiceContextList(tvb, pinfo, request_tree, &offset, stream_is_big_endian, 0);
4299 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4300 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
4301 proto_tree_add_uint (request_tree,hf_giop_req_id, tvb, offset-4, 4, request_id);
4303 response_expected = tvb_get_guint8( tvb, offset );
4304 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
4305 response_expected ? "two-way" : "one-way");
4306 proto_tree_add_item(request_tree, hf_giop_rsp_expected, tvb, offset, 1, ENC_NA);
4307 offset += 1;
4309 if( header->GIOP_version.minor > 0)
4311 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
4312 proto_tree_add_item(request_tree, hf_giop_reserved, tvb, offset-3, 3, ENC_NA);
4315 /* Prior to GIOP 1.2, MIOP profile address prefixed with 'MIOP' */
4317 miop[0] = get_CDR_octet (tvb, &offset);
4318 miop[1] = get_CDR_octet (tvb, &offset);
4319 miop[2] = get_CDR_octet (tvb, &offset);
4320 miop[3] = get_CDR_octet (tvb, &offset);
4322 if (miop[0] == 'M' && miop[1] == 'I' && miop[2] == 'O' && miop[3] == 'P')
4324 proto_tree_add_text (request_tree, tvb, offset - 4, 4, "Magic number: MIOP");
4325 decode_TaggedProfile (tvb, pinfo, request_tree, &offset, GIOP_HEADER_SIZE,
4326 stream_is_big_endian, NULL);
4328 else
4330 /* Wind back if not MIOP profile */
4332 offset -= 4;
4334 /* Length of object_key sequence */
4335 objkey_len = get_CDR_ulong (tvb, &offset, stream_is_big_endian,
4336 GIOP_HEADER_SIZE);
4337 tf = proto_tree_add_uint (request_tree, hf_giop_objekt_key_len, tvb, offset-4, 4, objkey_len);
4339 if (objkey_len > (guint32)tvb_reported_length_remaining(tvb, offset-4)) {
4340 expert_add_info_format(pinfo, tf, &ei_giop_length_too_big, "Object key length bigger than packet size");
4341 return;
4344 if (objkey_len > 0)
4346 get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
4347 proto_tree_add_item(request_tree, hf_giop_objekt_key, tvb,
4348 offset - objkey_len, objkey_len, ENC_NA);
4352 /* length of operation string and string */
4353 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
4354 proto_tree_add_uint (request_tree, hf_giop_req_operation_len, tvb, offset - 4 - len, 4, len);
4356 if( len > 0)
4358 col_append_fstr(pinfo->cinfo, COL_INFO, ": op=%s", operation);
4359 proto_tree_add_string(request_tree, hf_giop_req_operation,tvb, offset - len, len, operation);
4362 /* length of requesting_principal string */
4363 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
4364 tf = proto_tree_add_uint (request_tree, hf_giop_req_principal_len, tvb, offset - 4, 4, len);
4366 if (len > (guint32)tvb_reported_length_remaining(tvb, offset-4)) {
4367 expert_add_info_format(pinfo, tf, &ei_giop_length_too_big, "Requesting Principal length bigger than packet size");
4368 return;
4371 if( len > 0)
4373 get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
4374 proto_tree_add_string(request_tree, hf_giop_req_principal, tvb, offset - len, len,
4375 make_printable_string(requesting_principal, len));
4380 * Save FN,reqid,and operation for later. Add sub_handle later.
4381 * But only if user is NOT clicking.
4383 if (! pinfo->fd->flags.visited)
4384 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
4385 request_id,operation,NULL);
4389 * Call subdissector here before freeing "operation" and "key"
4390 * pass request_id also.
4391 * First try an find an explicit sub_dissector, then if that
4392 * fails, try the heuristic method.
4397 header->req_id = request_id; /* save for sub dissector */
4398 repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
4401 if(repoid) {
4402 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
4405 /* Only call heuristic if no explicit dissector was found */
4407 if (! exres) {
4408 exres = try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
4411 if (!exres && !strcmp(giop_op_is_a, operation) && request_tree) {
4412 const gchar *type_id;
4413 len = get_CDR_string(tvb, &type_id, &offset, stream_is_big_endian, 0);
4414 proto_tree_add_uint (request_tree, hf_giop_type_id_len, tvb, offset - 4 - len, 4, len);
4415 proto_tree_add_string(request_tree, hf_giop_type_id, tvb, offset - len, len, type_id);
4418 if(! exres) {
4419 gint stub_length = tvb_reported_length_remaining(tvb, offset);
4420 proto_tree_add_item(request_tree, hf_giop_stub_data, tvb,
4421 offset, stub_length, ENC_NA);
4425 /** The format of a GIOP 1.2 RequestHeader message is
4426 * (CORBA 2.4, sec. 15.4.2):
4428 * struct RequestHeader_1_2 {
4429 * unsigned long request_id;
4430 * octet response_flags;
4431 * octet reserved[3];
4432 * TargetAddress target;
4433 * string operation;
4434 * IOP::ServiceContextList service_context;
4435 * // requesting_principal not in GIOP 1.2
4436 * };
4438 static void
4439 dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
4440 proto_tree * tree,
4441 MessageHeader * header, gboolean stream_is_big_endian)
4443 guint32 offset = 0;
4444 guint32 request_id;
4445 guint32 len = 0;
4446 const gchar *reserved;
4447 const gchar *operation = NULL;
4448 proto_tree *request_tree;
4449 proto_item *tf;
4450 gboolean exres = FALSE; /* result of trying explicit dissectors */
4452 guint32 objkey_len = 0; /* object key length */
4453 const gchar *objkey = NULL; /* object key sequence */
4454 gchar *repoid = NULL; /* from object key lookup in objkey hash */
4456 tf = proto_tree_add_text (tree, tvb, offset, -1, "General Inter-ORB Protocol Request");
4457 request_tree = proto_item_add_subtree (tf, ett_giop_request);
4459 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
4460 header->req_id = request_id;
4461 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
4462 proto_tree_add_uint (request_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
4464 proto_tree_add_item(request_tree, hf_giop_response_flag, tvb,
4465 offset, 1, ENC_NA);
4466 offset += 1;
4468 get_CDR_octet_seq( tvb, &reserved, &offset, 3);
4469 proto_tree_add_item(request_tree, hf_giop_reserved, tvb, offset-3, 3, ENC_NA);
4471 dissect_target_address(tvb, pinfo, &offset, request_tree, stream_is_big_endian,
4472 &objkey_len, &objkey);
4473 if (objkey) {
4474 repoid = get_repoid_from_objkey(giop_objkey_hash, objkey, objkey_len);
4477 /* length of operation string and string */
4478 len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
4479 proto_tree_add_uint (request_tree, hf_giop_req_operation_len, tvb, offset - 4 - len, 4, len);
4481 if( len > 0)
4483 col_append_fstr(pinfo->cinfo, COL_INFO, ": op=%s", operation);
4484 proto_tree_add_string(request_tree, hf_giop_req_operation,tvb, offset - len, len, operation);
4488 * Decode IOP::ServiceContextList
4490 decode_ServiceContextList(tvb, pinfo, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
4493 * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
4494 * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
4495 * GIOP octet stream start.
4498 if (tvb_reported_length_remaining(tvb, offset) > 0)
4500 set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
4504 * Save FN,reqid,and operation for later. Add sub_handle later.
4505 * But only if user is NOT clicking.
4508 if (! pinfo->fd->flags.visited)
4509 giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
4510 request_id,operation,NULL);
4514 * Call sub dissector.
4515 * First try an find a explicit sub_dissector, then if that
4516 * fails, try the heuristic method.
4519 if(repoid) {
4520 exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
4523 /* Only call heuristic if no explicit dissector was found */
4525 if (! exres) {
4526 exres = try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
4529 if (!exres && !strcmp(giop_op_is_a, operation) && request_tree) {
4530 const gchar *type_id;
4531 len = get_CDR_string(tvb, &type_id, &offset, stream_is_big_endian, 0);
4532 proto_tree_add_uint (request_tree, hf_giop_type_id_len, tvb, offset - 4 - len, 4, len);
4533 proto_tree_add_string(request_tree, hf_giop_type_id, tvb, offset - len, len, type_id);
4536 if(! exres) {
4537 gint stub_length = tvb_reported_length_remaining(tvb, offset);
4538 if (stub_length > 0)
4539 proto_tree_add_item(request_tree, hf_giop_stub_data, tvb,
4540 offset, stub_length, ENC_NA);
4544 static void
4545 dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
4546 proto_tree * tree, MessageHeader * header,
4547 gboolean stream_is_big_endian)
4549 guint32 offset = 0;
4550 guint32 request_id;
4551 guint32 len = 0;
4552 proto_tree *locate_request_tree;
4553 proto_item *tf;
4555 tf = proto_tree_add_text (tree, tvb, offset, -1, "General Inter-ORB Locate Request");
4556 locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
4558 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4559 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u op=LocateRequest", request_id);
4560 proto_tree_add_uint (locate_request_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
4562 if(header->GIOP_version.minor < 2)
4564 len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4565 proto_tree_add_uint (locate_request_tree, hf_giop_objekt_key_len, tvb, offset-4, 4, len);
4567 if (len > (guint32)tvb_reported_length_remaining(tvb, offset-4)) {
4568 expert_add_info_format(pinfo, tf, &ei_giop_length_too_big, "Object key length bigger than packet size");
4569 return;
4572 if (len > 0) {
4573 proto_tree_add_item(locate_request_tree, hf_giop_objekt_key, tvb, offset-len, len, ENC_NA);
4576 else /* GIOP 1.2 and higher */
4578 dissect_target_address(tvb, pinfo, &offset, locate_request_tree,
4579 stream_is_big_endian, NULL, NULL);
4583 static void
4584 dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
4585 proto_tree * tree, MessageHeader * header,
4586 gboolean stream_is_big_endian)
4588 guint32 offset = 0;
4589 guint32 request_id;
4590 guint32 locate_status;
4591 guint16 addr_disp;
4593 proto_tree *locate_reply_tree;
4594 proto_item *tf;
4596 tf = proto_tree_add_text (tree, tvb, offset, -1, "General Inter-ORB Locate Reply");
4597 locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
4599 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4600 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
4601 proto_tree_add_uint (locate_reply_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
4603 locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4604 proto_tree_add_uint (locate_reply_tree, hf_giop_locale_status, tvb, offset-4, 4, locate_status);
4606 /* Decode the LocateReply body.
4608 * For GIOP 1.0 and 1.1 body immediately follows header.
4609 * For GIOP 1.2 it is aligned on 8 octet boundary so need to
4610 * spin up.
4613 if (header->GIOP_version.minor > 1) {
4614 while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
4615 ++(offset);
4618 switch(locate_status) {
4619 case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
4620 case OBJECT_FORWARD_PERM:
4621 decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
4622 break;
4623 case LOC_SYSTEM_EXCEPTION:
4624 decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
4625 break;
4626 case LOC_NEEDS_ADDRESSING_MODE:
4627 addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4628 proto_tree_add_uint (tree, hf_giop_addressing_disposition, tvb, offset-2, 2, addr_disp);
4629 break;
4630 default: /* others have no reply body */
4631 break;
4636 static void
4637 dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
4638 gboolean stream_is_big_endian)
4640 guint32 offset = 0;
4641 guint32 request_id;
4642 proto_tree *fragment_tree;
4643 proto_item *tf;
4645 tf = proto_tree_add_text (tree, tvb, offset, -1, "General Inter-ORB Fragment");
4646 fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
4648 request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
4649 col_append_fstr(pinfo->cinfo, COL_INFO, " id=%u", request_id);
4650 proto_tree_add_uint (fragment_tree, hf_giop_req_id, tvb, offset-4, 4, request_id);
4654 /* Main entry point */
4656 static int dissect_giop_common (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_) {
4657 guint offset = 0;
4658 MessageHeader header;
4659 tvbuff_t *payload_tvb;
4661 proto_tree *giop_tree, *header_tree, *header_version_tree;
4662 proto_item *ti, *version_item;
4663 guint message_size;
4664 gboolean stream_is_big_endian;
4666 /* DEBUG */
4668 #if DEBUG
4669 giop_dump_collection(cd_module_hash);
4670 giop_dump_collection(cd_objkey_hash);
4671 giop_dump_collection(cd_heuristic_users);
4672 giop_dump_collection(cd_complete_reply_hash);
4673 giop_dump_collection(cd_complete_request_list);
4674 #endif
4676 header.exception_id = NULL;
4678 col_set_str(pinfo->cinfo, COL_PROTOCOL, "GIOP");
4679 col_clear(pinfo->cinfo, COL_INFO);
4681 ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, ENC_NA);
4682 giop_tree = proto_item_add_subtree (ti, ett_giop);
4684 /* Get raw header data */
4685 tvb_memcpy (tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
4686 stream_is_big_endian = is_big_endian (&header);
4688 /* Dissect GIOP header */
4689 ti = proto_tree_add_text (giop_tree, tvb, offset, GIOP_HEADER_SIZE, "GIOP Header");
4690 header_tree = proto_item_add_subtree (ti, ett_giop_header);
4691 proto_tree_add_item(header_tree, hf_giop_message_magic, tvb, 0, 4, ENC_NA|ENC_ASCII);
4693 version_item = proto_tree_add_text (header_tree, tvb, 4, 2,
4694 "Version: %u.%u", header.GIOP_version.major, header.GIOP_version.minor);
4695 header_version_tree = proto_item_add_subtree (version_item, ett_giop_header_version);
4696 proto_tree_add_item(header_version_tree, hf_giop_message_major_version, tvb, 4, 1, ENC_NA);
4697 proto_tree_add_item(header_version_tree, hf_giop_message_minor_version, tvb, 5, 1, ENC_NA);
4699 if ((header.GIOP_version.major != GIOP_MAJOR) ||
4700 (header.GIOP_version.minor > GIOP_MINOR))
4702 /* Bad version number; should we note that and dissect the rest
4703 as data, or should this be done outside dissect_giop_common()
4704 (which is called as the PDU dissector for GIOP-over-TCP,
4705 so it can't return anything), with the test returning FALSE
4706 on the theory that it might have been some other packet that
4707 happened to begin with "GIOP"? We do the former, for now.
4708 If we should return FALSE, we should do so *without* setting
4709 the "Info" column, *without* setting the "Protocol" column,
4710 and *without* adding anything to the protocol tree. */
4711 col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
4712 header.GIOP_version.major, header.GIOP_version.minor);
4714 expert_add_info_format(pinfo, version_item, &ei_giop_version_not_supported, "Version %u.%u not supported",
4715 header.GIOP_version.major, header.GIOP_version.minor);
4717 payload_tvb = tvb_new_subset_remaining (tvb, GIOP_HEADER_SIZE);
4718 call_dissector(data_handle,payload_tvb, pinfo, tree);
4719 return tvb_length(tvb);
4722 switch (header.GIOP_version.minor)
4724 case 2:
4725 case 1:
4726 ti = proto_tree_add_bitmask(header_version_tree, tvb, 6,
4727 hf_giop_message_flags, ett_giop_message_flags,
4728 giop_message_flags, ENC_BIG_ENDIAN);
4729 if ((header.flags & GIOP_MESSAGE_FLAGS_ENDIANNESS) == 0)
4730 proto_item_append_text(ti, ", (Big Endian)"); /* hack to show "Big Endian" when endianness flag == 0 */
4731 break;
4732 case 0:
4733 proto_tree_add_text (header_version_tree, tvb, 6, 1,
4734 "Byte ordering: %s-endian",
4735 (stream_is_big_endian) ? "big" : "little");
4736 ti = proto_tree_add_boolean(header_tree, hf_giop_message_flags_little_endian, tvb, 6, 1, stream_is_big_endian ? 0 : 1);
4737 PROTO_ITEM_SET_HIDDEN(ti);
4738 break;
4741 proto_tree_add_item(header_tree, hf_giop_message_type, tvb, 7, 1, ENC_NA);
4743 if (stream_is_big_endian)
4745 message_size = tvb_get_ntohl(tvb, 8);
4747 else
4749 message_size = tvb_get_letohl(tvb, 8);
4752 col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s, s=%u",
4753 header.GIOP_version.major, header.GIOP_version.minor,
4754 val_to_str(header.message_type, giop_message_types, "Unknown message type (0x%02x)"),
4755 message_size);
4757 ti = proto_tree_add_uint(header_tree, hf_giop_message_size, tvb, 8, 4, message_size);
4758 if (message_size > GIOP_MAX_MESSAGE_SIZE)
4760 expert_add_info_format(pinfo, ti, &ei_giop_message_size_too_big,
4761 "Message size %u is too big, perhaps it's an endian issue?", message_size);
4762 return 8;
4765 if (header.flags & GIOP_MESSAGE_FLAGS_ZIOP_ENABLED)
4767 gint rem_len;
4769 rem_len = tvb_length_remaining(tvb, GIOP_HEADER_SIZE);
4770 if (rem_len <= 0)
4771 return 8;
4773 payload_tvb = tvb_child_uncompress(tvb, tvb, GIOP_HEADER_SIZE, rem_len);
4774 if (payload_tvb) {
4775 add_new_data_source (pinfo, payload_tvb, "decompressed Content");
4776 } else {
4777 /* Decompression failed. */
4778 /* XXX: Consider: add expert item ? do data dissection ? */
4779 return 8;
4781 } else {
4782 payload_tvb = tvb_new_subset_remaining (tvb, GIOP_HEADER_SIZE);
4785 switch (header.message_type)
4788 case Request:
4789 if(header.GIOP_version.minor < 2)
4791 dissect_giop_request_1_1 (payload_tvb, pinfo, tree,
4792 &header, stream_is_big_endian);
4794 else
4796 dissect_giop_request_1_2 (payload_tvb, pinfo, tree,
4797 &header, stream_is_big_endian);
4800 break;
4803 case Reply:
4804 if(header.GIOP_version.minor < 2)
4806 dissect_giop_reply (payload_tvb, pinfo, tree, &header,
4807 stream_is_big_endian);
4809 else
4811 dissect_giop_reply_1_2 (payload_tvb, pinfo, tree,
4812 &header, stream_is_big_endian);
4814 break;
4815 case CancelRequest:
4816 dissect_giop_cancel_request(payload_tvb, pinfo, tree,
4817 stream_is_big_endian);
4818 break;
4819 case LocateRequest:
4820 dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
4821 stream_is_big_endian);
4822 break;
4823 case LocateReply:
4824 dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
4825 stream_is_big_endian);
4826 break;
4827 case Fragment:
4828 dissect_giop_fragment(payload_tvb, pinfo, tree,
4829 stream_is_big_endian);
4830 break;
4831 default:
4832 break;
4834 } /* switch message_type */
4835 return tvb_length(tvb);
4838 static guint
4839 get_giop_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset _U_)
4842 MessageHeader header;
4843 guint message_size;
4845 if (tvb_get_ntohl(tvb, 0) != GIOP_MAGIC_NUMBER)
4846 return 0;
4848 /* Get minimal header information to determine endianness, size */
4849 header.GIOP_version.minor = tvb_get_guint8(tvb, 5);
4850 header.flags = tvb_get_guint8(tvb, 6);
4852 if (is_big_endian (&header))
4853 message_size = tvb_get_ntohl(tvb, 8);
4854 else
4855 message_size = tvb_get_letohl(tvb, 8);
4857 /* Make sure the size is reasonable, otherwise just take the header */
4858 if (message_size > GIOP_MAX_MESSAGE_SIZE)
4859 return GIOP_HEADER_SIZE;
4861 return message_size + GIOP_HEADER_SIZE;
4864 static gboolean
4865 dissect_giop_heur (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void *);
4868 gboolean dissect_giop(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
4869 return dissect_giop_heur(tvb, pinfo, tree, NULL);
4873 static int
4874 dissect_giop_tcp (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data) {
4876 if (tvb_get_ntohl(tvb, 0) != GIOP_MAGIC_NUMBER) {
4878 if ( tvb_memeql(tvb, 0, ZIOP_MAGIC ,4) == 0)
4879 if (!dissect_ziop_heur(tvb, pinfo, tree, NULL))
4880 return 0;
4882 return tvb_length(tvb);
4885 tcp_dissect_pdus(tvb, pinfo, tree, giop_desegment, GIOP_HEADER_SIZE,
4886 get_giop_pdu_len, dissect_giop_common, data);
4887 return tvb_length(tvb);
4890 static gboolean
4891 dissect_giop_heur (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data) {
4893 guint tot_len;
4895 conversation_t *conversation;
4896 /* check magic number and version */
4899 /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
4901 tot_len = tvb_length(tvb);
4903 if (tot_len < GIOP_HEADER_SIZE) /* tot_len < 12 */
4905 /* Not enough data captured to hold the GIOP header; don't try
4906 to interpret it as GIOP. */
4907 return FALSE;
4910 if (tvb_get_ntohl(tvb, 0) != GIOP_MAGIC_NUMBER)
4911 return FALSE;
4913 if ( pinfo->ptype == PT_TCP )
4916 * Make the GIOP dissector the dissector for this conversation.
4918 * If this isn't the first time this packet has been processed,
4919 * we've already done this work, so we don't need to do it
4920 * again.
4922 if (!pinfo->fd->flags.visited)
4924 conversation = find_or_create_conversation(pinfo);
4926 /* Set dissector */
4927 conversation_set_dissector(conversation, giop_tcp_handle);
4929 dissect_giop_tcp (tvb, pinfo, tree, data);
4931 else
4933 dissect_giop_common (tvb, pinfo, tree, data);
4936 return TRUE;
4940 void
4941 proto_register_giop (void)
4943 static hf_register_info hf[] = {
4944 { &hf_giop_message_magic,
4945 { "Magic", "giop.magic",
4946 FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }
4948 { &hf_giop_message_major_version,
4949 { "Major Version", "giop.major_version",
4950 FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }
4952 { &hf_giop_message_minor_version,
4953 { "Minor Version", "giop.minor_version",
4954 FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }
4956 { &hf_giop_message_flags,
4957 { "Message Flags", "giop.flags",
4958 FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }
4961 { &hf_giop_message_flags_ziop_enabled,
4962 { "ZIOP Enabled", "giop.flags.ziop_enabled",
4963 FT_BOOLEAN, 8, NULL, GIOP_MESSAGE_FLAGS_ZIOP_ENABLED, NULL, HFILL }
4966 { &hf_giop_message_flags_ziop_supported,
4967 { "ZIOP Supported", "giop.flags.ziop_supported",
4968 FT_BOOLEAN, 8, NULL, GIOP_MESSAGE_FLAGS_ZIOP_SUPPORTED, NULL, HFILL }
4971 { &hf_giop_message_flags_fragment,
4972 { "Fragment", "giop.flags.fragment",
4973 FT_BOOLEAN, 8, NULL, GIOP_MESSAGE_FLAGS_FRAGMENT, NULL, HFILL }
4976 { &hf_giop_message_flags_little_endian,
4977 { "Little Endian", "giop.flags.little_endian",
4978 FT_BOOLEAN, 8, NULL, GIOP_MESSAGE_FLAGS_ENDIANNESS, NULL, HFILL }
4981 { &hf_giop_message_type,
4982 { "Message type", "giop.type",
4983 FT_UINT8, BASE_DEC, giop_message_types, 0x0, NULL, HFILL }
4986 { &hf_giop_message_size,
4987 { "Message size", "giop.len",
4988 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
4991 { &hf_giop_repoid,
4992 { "Repository ID", "giop.repoid",
4993 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
4996 { &hf_giop_string_length,
4997 { "String Length", "giop.strlen",
4998 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5001 { &hf_giop_sequence_length,
5002 { "Sequence Length", "giop.seqlen",
5003 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5006 { &hf_giop_profile_id,
5007 { "Profile ID", "giop.profid",
5008 FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, NULL, HFILL }
5012 { &hf_giop_type_id,
5013 { "IOR::type_id", "giop.typeid",
5014 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5017 { &hf_giop_type_id_len,
5018 { "Type Id length", "giop.typeid_len",
5019 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5022 { &hf_giop_iiop_v_maj,
5023 { "IIOP Major Version", "giop.iiop_vmaj",
5024 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
5027 { &hf_giop_iiop_v_min,
5028 { "IIOP Minor Version", "giop.iiop_vmin",
5029 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
5032 #if 0
5033 { &hf_giop_compressed,
5034 { "ZIOP", "giop.compressed",
5035 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
5037 #endif
5039 { &hf_giop_endianness,
5040 { "Endianness", "giop.endianness",
5041 FT_UINT8, BASE_DEC, VALS(giop_endianness_vals), 0x0, NULL, HFILL }
5044 { &hf_giop_locale_status,
5045 { "Locate status", "giop.locale_status",
5046 FT_UINT32, BASE_DEC, VALS(giop_locate_status_types), 0x0, NULL, HFILL }
5049 { &hf_giop_addressing_disposition,
5050 { "Addressing Disposition", "giop.addressing_disposition",
5051 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
5054 { &hf_giop_profile_data,
5055 { "Profile Data", "giop.profile_data",
5056 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5059 { &hf_giop_component_data,
5060 { "Component Data", "giop.component_data",
5061 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5064 { &hf_giop_rt_corba_priority,
5065 { "RTCorbaPriority", "giop.rt_corba_priority",
5066 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
5069 { &hf_giop_context_data_len,
5070 { "Context Data Length", "giop.context_data_len",
5071 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5074 { &hf_giop_target_address_discriminant,
5075 { "TargetAddress", "giop.target_address.discriminant",
5076 FT_UINT16, BASE_DEC, VALS(target_address_discriminant_vals), 0x0, NULL, HFILL }
5079 { &hf_giop_target_address_key_addr_len,
5080 { "Key Address Length", "giop.target_address.key_addr_len",
5081 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5084 { &hf_giop_target_address_key_addr,
5085 { "Key Address", "giop.target_address.key_addr",
5086 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5089 { &hf_giop_target_address_ref_addr_len,
5090 { "Reference Address Length", "giop.target_address.ref_addr_len",
5091 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5094 { &hf_giop_context_data,
5095 { "Context Data", "giop.context_data",
5096 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5099 { &hf_giop_char_data,
5100 { "char data", "giop.char_data",
5101 FT_UINT32, BASE_DEC, &giop_code_set_vals_ext, 0x0, NULL, HFILL }
5104 { &hf_giop_wchar_data,
5105 { "wchar data", "giop.wchar_data",
5106 FT_UINT32, BASE_DEC, &giop_code_set_vals_ext, 0x0, NULL, HFILL }
5109 { &hf_giop_IIOP_tag,
5110 { "IIOP Component TAG", "giop.iioptag",
5111 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5114 #if 0
5115 { &hf_giop_IOR_tag,
5116 { "IOR Profile TAG", "giop.iortag",
5117 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
5119 #endif
5121 { &hf_giop_TCKind,
5122 { "TypeCode enum", "giop.TCKind",
5123 FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, NULL, HFILL }
5126 { &hf_giop_typecode_count,
5127 { "TypeCode count", "giop.tccount",
5128 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5131 { &hf_giop_typecode_default_used,
5132 { "default_used", "giop.tcdefault_used",
5133 FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5136 { &hf_giop_typecode_digits,
5137 { "Digits", "giop.tcdigits",
5138 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
5142 { &hf_giop_typecode_length,
5143 { "Length", "giop.tclength",
5144 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5147 { &hf_giop_typecode_max_length,
5148 { "Maximum length", "giop.tcmaxlen",
5149 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5152 { &hf_giop_typecode_member_name,
5153 { "TypeCode member name", "giop.tcmemname",
5154 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5157 { &hf_giop_typecode_name,
5158 { "TypeCode name", "giop.tcname",
5159 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5162 { &hf_giop_typecode_scale,
5163 { "Scale", "giop.tcscale",
5164 FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
5167 { &hf_giop_typecode_ValueModifier,
5168 { "ValueModifier", "giop.tcValueModifier",
5169 FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
5172 { &hf_giop_typecode_Visibility,
5173 { "Visibility", "giop.tcVisibility",
5174 FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
5179 { &hf_giop_type_boolean,
5180 { "TypeCode boolean data", "giop.tcboolean",
5181 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }
5184 { &hf_giop_type_char,
5185 { "TypeCode char data", "giop.tcchar",
5186 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
5189 { &hf_giop_type_double,
5190 { "TypeCode double data", "giop.tcdouble",
5191 FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }
5194 { &hf_giop_type_enum,
5195 { "TypeCode enum data", "giop.tcenumdata",
5196 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5200 * float as double ?? -- FIX
5203 { &hf_giop_type_float,
5204 { "TypeCode float data", "giop.tcfloat",
5205 FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }
5208 { &hf_giop_type_long,
5209 { "TypeCode long data", "giop.tclongdata",
5210 FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5213 { &hf_giop_type_octet,
5214 { "TypeCode octet data", "giop.tcoctet",
5215 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
5218 { &hf_giop_type_short,
5219 { "TypeCode short data", "giop.tcshortdata",
5220 FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
5223 { &hf_giop_type_string,
5224 { "TypeCode string data", "giop.tcstring",
5225 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5228 { &hf_giop_type_ulong,
5229 { "TypeCode ulong data", "giop.tculongdata",
5230 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5233 { &hf_giop_type_ushort,
5234 { "TypeCode ushort data", "giop.tcushortdata",
5235 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
5239 * IIOP Module - Chapter 15.10.2
5242 { &hf_giop_iiop_host,
5243 { "IIOP::Profile_host", "giop.iiop.host",
5244 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5247 { &hf_giop_iiop_port,
5248 { "IIOP::Profile_port", "giop.iiop.port",
5249 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
5253 * IIOP ServiceContext
5256 { &hf_giop_iop_vscid,
5257 { "VSCID", "giop.iiop.vscid",
5258 FT_UINT32, BASE_HEX, VALS(service_context_ids), 0xffffff00, NULL, HFILL }
5261 { &hf_giop_iop_scid,
5262 { "SCID", "giop.iiop.scid",
5263 FT_UINT32, BASE_HEX, NULL, 0x000000ff, NULL, HFILL }
5266 { &hf_giop_req_id,
5267 { "Request id", "giop.request_id",
5268 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
5271 { &hf_giop_req_operation_len,
5272 { "Operation length", "giop.request_op_len",
5273 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
5276 { &hf_giop_req_operation,
5277 { "Request operation", "giop.request_op",
5278 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5281 { &hf_giop_req_principal_len,
5282 { "Requesting Principal Length", "giop.request_principal_len",
5283 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
5286 { &hf_giop_req_principal,
5287 { "Requesting Principal", "giop.request_principal",
5288 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5291 { &hf_giop_reply_status,
5292 { "Reply status", "giop.replystatus",
5293 FT_UINT32, BASE_DEC, VALS(reply_status_types), 0x0, NULL, HFILL }
5296 { &hf_giop_exception_len,
5297 { "Exception length", "giop.exceptionid_len",
5298 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5301 { &hf_giop_exception_id,
5302 { "Exception id", "giop.exceptionid",
5303 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
5306 { &hf_giop_objekt_key,
5307 { "Object Key", "giop.objektkey",
5308 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
5311 { &hf_giop_objekt_key_len,
5312 { "Object Key length", "giop.objektkey_len",
5313 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5316 { &hf_giop_rsp_expected,
5317 { "Response expected", "giop.rsp_expected",
5318 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
5321 { &hf_giop_response_flag,
5322 { "Response flags", "giop.response_flag",
5323 FT_UINT8, BASE_DEC, VALS(response_flags_vals), 0x0, NULL, HFILL }
5326 { &hf_giop_reserved,
5327 { "Reserved", "giop.reserved",
5328 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
5331 { &hf_giop_stub_data,
5332 { "Stub data", "giop.stub_data",
5333 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
5336 { &hf_giop_address_disp,
5337 { "Addressing Disposition", "giop.address_disposition",
5338 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
5341 { &hf_giop_minor_code_value,
5342 { "Minor code value", "giop.minor_code_value",
5343 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5346 { &hf_giop_completion_status,
5347 { "Completion Status", "giop.completion_status",
5348 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
5351 { &hf_giop_reply_body,
5352 { "Reply body", "giop.reply_body",
5353 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
5357 static gint *ett[] = {
5358 &ett_giop,
5359 &ett_giop_header,
5360 &ett_giop_header_version,
5361 &ett_giop_message_flags,
5362 &ett_giop_reply,
5363 &ett_giop_request,
5364 &ett_giop_cancel_request,
5365 &ett_giop_locate_request,
5366 &ett_giop_locate_reply,
5367 &ett_giop_fragment,
5368 &ett_giop_scl,
5369 &ett_giop_scl_st1,
5370 &ett_giop_ior
5374 static ei_register_info ei[] = {
5375 { &ei_giop_unknown_typecode_datatype, { "giop.unknown_typecode_datatype", PI_PROTOCOL, PI_WARN, "Unknown typecode data type", EXPFILL }},
5376 { &ei_giop_unknown_sign_value, { "giop.unknown_sign_value", PI_PROTOCOL, PI_WARN, "Unknown sign value in fixed type", EXPFILL }},
5377 { &ei_giop_unknown_tckind, { "giop.unknown_tckind", PI_PROTOCOL, PI_WARN, "Unknown TCKind", EXPFILL }},
5378 { &ei_giop_length_too_big, { "giop.length_too_big", PI_MALFORMED, PI_ERROR, "length bigger than packet size", EXPFILL }},
5379 { &ei_giop_version_not_supported, { "giop.version_not_supported", PI_PROTOCOL, PI_WARN, "Version not supported", EXPFILL }},
5380 { &ei_giop_message_size_too_big, { "giop.message_size_too_big", PI_PROTOCOL, PI_WARN, "Message size is too big", EXPFILL }},
5381 { &ei_giop_invalid_v_minor, { "giop.invalid_v_minor", PI_PROTOCOL, PI_WARN, "Invalid v_minor value", EXPFILL }},
5384 module_t *giop_module;
5385 expert_module_t* expert_giop;
5387 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP", "giop");
5389 /* Register by name */
5390 giop_tcp_handle = new_register_dissector("giop", dissect_giop_tcp, proto_giop);
5392 proto_register_field_array (proto_giop, hf, array_length (hf));
5393 proto_register_subtree_array (ett, array_length (ett));
5394 expert_giop = expert_register_protocol(proto_giop);
5395 expert_register_field_array(expert_giop, ei, array_length(ei));
5398 /* register init routine */
5400 register_init_routine( &giop_init); /* any init stuff */
5402 /* register preferences */
5403 giop_module = prefs_register_protocol(proto_giop, NULL);
5404 prefs_register_bool_preference(giop_module, "desegment_giop_messages",
5405 "Reassemble GIOP messages spanning multiple TCP segments",
5406 "Whether the GIOP dissector should reassemble messages spanning multiple TCP segments."
5407 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5408 &giop_desegment);
5409 prefs_register_filename_preference(giop_module, "ior_txt", "Stringified IORs",
5410 "File containing stringified IORs, one per line.", &giop_ior_file);
5413 * Init the giop user module hash tables here, as giop users
5414 * will populate it via register_giop_user_module BEFORE my
5415 * own giop_init() is called.
5418 giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
5424 void proto_reg_handoff_giop (void) {
5425 data_handle = find_dissector("data");
5426 heur_dissector_add("tcp", dissect_giop_heur, proto_giop);
5427 /* Support DIOP (GIOP/UDP) */
5428 heur_dissector_add("udp", dissect_giop_heur, proto_giop);
5429 dissector_add_handle("tcp.port", giop_tcp_handle); /* for "decode-as" */
5436 * Decode IOR
5438 * Ref Corba v2.4.2 Chapter 13
5444 module IOP{
5446 typedef unsigned long ProfileId;
5448 const ProfileId TAG_INTERNET_IOP = 0;
5449 const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
5451 struct TaggedProfile {
5452 ProfileId tag;
5453 sequence <octet> profile_data;
5456 struct IOR {
5457 string type_id;
5458 sequence <TaggedProfile> profiles;
5461 typedef unsigned long ComponentId;
5463 struct TaggedComponent {
5464 ComponentId tag;
5465 sequence <octet> component_data;
5468 typedef sequence <TaggedComponent> MultipleComponentProfile;
5474 static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
5475 guint32 boundary, gboolean stream_is_big_endian) {
5478 guint32 seqlen_p; /* sequence length of profiles */
5479 guint32 u_octet4;
5481 proto_tree *tree = NULL; /* IOR tree */
5482 proto_item *tf;
5484 const gchar *repobuf; /* for repository ID */
5486 guint32 i;
5488 /* create a subtree */
5489 tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
5490 tree = proto_item_add_subtree (tf, ett_giop_ior);
5492 /* Get type_id == Repository ID */
5494 u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
5495 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5496 *offset-u_octet4-(int)sizeof(u_octet4),4,u_octet4);
5497 if (u_octet4 > 0) {
5498 proto_tree_add_string(tree,hf_giop_type_id,tvb,
5499 *offset-u_octet4,u_octet4,repobuf);
5502 /* Now get a sequence of profiles */
5503 /* Get sequence length (number of elements) */
5505 seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5506 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5507 *offset-(int)sizeof(seqlen_p),4,seqlen_p);
5509 /* fetch all TaggedProfiles in this sequence */
5510 for (i=0; i< seqlen_p; i++) {
5511 decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
5515 static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
5516 guint32 boundary, gboolean stream_is_big_endian, const gchar *repobuf) {
5518 guint32 seqlen_pd; /* sequence length of profile data */
5519 guint32 pidtag; /* profile ID TAG */
5520 const gchar *profile_data; /* profile_data pointer */
5521 guint32 new_boundary; /* for encapsulations encountered */
5522 gboolean new_big_endianness; /* for encapsulations encountered */
5523 proto_item *ti;
5525 /* Get ProfileId tag */
5526 pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5527 ti = proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
5528 *offset-(int)sizeof(pidtag),4,pidtag);
5530 /* get sequence length, new endianness and boundary for encapsulation */
5531 seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
5532 stream_is_big_endian, boundary,
5533 &new_big_endianness, &new_boundary);
5535 /* return if zero length sequence */
5536 if(seqlen_pd == 0)
5537 return;
5541 * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
5542 * decode it, otherwise just dump the octet sequence
5544 * also, store IOR in our objectkey hash
5546 * TODO - handle other TAGS
5549 switch(pidtag) {
5550 case IOP_TAG_INTERNET_IOP:
5552 decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianness, repobuf, TRUE);
5553 break;
5555 default:
5557 if (seqlen_pd-1 > (guint32)tvb_reported_length_remaining(tvb, *offset-4)) {
5558 expert_add_info_format(pinfo, ti, &ei_giop_length_too_big, "Profile data bigger than packet size");
5559 break;
5562 /* fetch all octets in this sequence , but skip endianness */
5563 get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
5565 /* Make a printable string */
5566 proto_tree_add_string(tree, hf_giop_profile_data, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
5567 make_printable_string( profile_data, seqlen_pd -1));
5568 break;
5575 * Decode IIOP IOR Profile
5576 * Ref Chap 15.7.2 in Corba Spec
5580 static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
5581 guint32 boundary, gboolean stream_is_big_endian,
5582 const gchar *repo_id_buf,
5583 gboolean store_flag) {
5585 guint32 i; /* loop index */
5587 guint8 v_major,v_minor; /* IIOP version */
5588 const gchar *buf;
5589 guint32 u_octet4; /* u long */
5590 guint16 u_octet2; /* u short */
5591 guint32 seqlen; /* generic sequence length */
5592 guint32 seqlen1; /* generic sequence length */
5593 const gchar *objkey; /* object key pointer */
5594 proto_item *ti, *ti_minor;
5597 /* Get major/minor version */
5599 v_major = get_CDR_octet(tvb,offset);
5600 v_minor = get_CDR_octet(tvb,offset);
5602 proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
5603 *offset-2,1,v_major );
5604 ti_minor = proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
5605 *offset-1,1,v_minor );
5607 /* host */
5608 u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
5609 proto_tree_add_uint(tree,hf_giop_string_length,tvb,
5610 *offset-u_octet4-4,4,u_octet4);
5611 if (u_octet4 > 0) {
5612 proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
5613 *offset-u_octet4,u_octet4,buf);
5616 /* Port */
5618 u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
5619 proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
5620 *offset-2,2,u_octet2);
5622 /* Object Key - sequence<octet> object_key */
5623 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5624 ti = proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5625 *offset-4,4,seqlen);
5626 if (seqlen > (guint32)tvb_reported_length_remaining(tvb, *offset-4)) {
5627 expert_add_info_format(pinfo, ti, &ei_giop_length_too_big, "Sequence length bigger than packet size");
5628 return;
5631 if (seqlen > 0) {
5632 /* fetch all octets in this sequence */
5633 get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
5636 * Now we may have the Repository ID from earlier, as well
5637 * as the object key sequence and lengh. So lets store them in
5638 * our objectkey hash and free buffers.
5640 * But only insert if user is not clicking and repo id not NULL.
5644 if (repo_id_buf) {
5645 if (pinfo) {
5646 if(!pinfo->fd->flags.visited)
5647 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,ior_src_req_res);
5649 else {
5652 * No pinfo, but store anyway if flag set. eg: IOR read from file
5655 if (store_flag)
5656 insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,ior_src_file);
5660 proto_tree_add_item(tree, hf_giop_objekt_key, tvb, *offset -seqlen, seqlen, ENC_NA);
5664 * Now see if if it's v1.1 or 1.2, as they can contain
5665 * extra sequence of IOP::TaggedComponents
5669 switch(v_minor) {
5670 case 0:
5672 /* nothing extra */
5673 break;
5675 case 1:
5676 case 2:
5678 /* sequence of IOP::TaggedComponents */
5679 /* Ref Chap 13 in Corba Spec */
5681 /* get sequence length */
5682 seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5683 proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5684 *offset-4,4,seqlen);
5686 for (i=0; i< seqlen; i++) {
5687 /* get tag */
5688 u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5689 proto_tree_add_uint(tree, hf_giop_IIOP_tag, tvb, *offset-4, 4, u_octet4);
5691 /* get component_data */
5692 seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
5693 ti = proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
5694 *offset-4,4,seqlen1);
5695 if (seqlen1 > (guint32)tvb_reported_length_remaining(tvb, *offset-4)) {
5696 expert_add_info_format(pinfo, ti, &ei_giop_length_too_big, "Sequence length bigger than packet size");
5697 return;
5700 if (seqlen1 > 0) {
5701 get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
5702 proto_tree_add_string(tree, hf_giop_component_data, tvb, *offset -seqlen1, seqlen1,
5703 make_printable_string(buf, seqlen1));
5707 break;
5709 default:
5710 expert_add_info_format(pinfo, ti_minor, &ei_giop_invalid_v_minor, "Invalid v_minor value = %u", v_minor);
5711 break;
5716 /* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
5719 static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
5720 gboolean stream_is_big_endian,
5721 guint32 boundary) {
5723 guint32 length; /* string length */
5724 guint32 minor_code_value;
5725 guint32 completion_status;
5727 const gchar *buf; /* pointer to string buffer */
5729 length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
5730 proto_tree_add_uint(tree, hf_giop_exception_len, tvb, *offset-4, 4, length);
5732 if (length > 0)
5733 proto_tree_add_string(tree, hf_giop_exception_id, tvb,
5734 *offset - length, length, buf);
5736 minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
5737 completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
5739 proto_tree_add_uint(tree, hf_giop_minor_code_value, tvb, *offset-8, 4, minor_code_value);
5740 proto_tree_add_uint(tree, hf_giop_completion_status, tvb, *offset-4, 4, completion_status);
5744 * Editor modelines - http://www.wireshark.org/tools/modelines.html
5746 * Local variables:
5747 * c-basic-offset: 2
5748 * tab-width: 8
5749 * indent-tabs-mode: nil
5750 * End:
5752 * vi: set shiftwidth=2 tabstop=8 expandtab:
5753 * :indentSize=2:tabSize=8:noTabs=true: