/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 | | */ |