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