Coverage Report

Created: 2026-05-14 06:28

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