/src/wireshark/epan/dissectors/packet-ziop.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-ziop.c |
2 | | * Routines for CORBA ZIOP packet disassembly |
3 | | * Significantly based on packet-giop.c |
4 | | * Copyright 2009 Alvaro Vega Garcia <avega at tid dot es> |
5 | | * |
6 | | * According with GIOP Compression RFP revised submission |
7 | | * OMG mars/2008-12-20 |
8 | | * https://www.omg.org/spec/ZIOP/1.0/Beta1/PDF |
9 | | * |
10 | | * Wireshark - Network traffic analyzer |
11 | | * By Gerald Combs <gerald@wireshark.org> |
12 | | * Copyright 1998 Gerald Combs |
13 | | * |
14 | | * SPDX-License-Identifier: GPL-2.0-or-later |
15 | | */ |
16 | | |
17 | | |
18 | | #include "config.h" |
19 | | |
20 | | #include <epan/packet.h> |
21 | | #include <epan/expert.h> |
22 | | |
23 | | #include "packet-ziop.h" |
24 | | #include "packet-giop.h" |
25 | | #include "packet-tcp.h" |
26 | | |
27 | | /* |
28 | | * Set to 1 for DEBUG output - TODO make this a runtime option |
29 | | */ |
30 | | |
31 | | #define DEBUG 0 |
32 | | |
33 | | void proto_reg_handoff_ziop(void); |
34 | | void proto_register_ziop(void); |
35 | | |
36 | | /* |
37 | | * ------------------------------------------------------------------------------------------+ |
38 | | * Data/Variables/Structs |
39 | | * ------------------------------------------------------------------------------------------+ |
40 | | */ |
41 | | |
42 | | static int proto_ziop; |
43 | | |
44 | | /* |
45 | | * (sub)Tree declares |
46 | | */ |
47 | | |
48 | | static int hf_ziop_magic; |
49 | | static int hf_ziop_giop_version_major; |
50 | | static int hf_ziop_giop_version_minor; |
51 | | static int hf_ziop_flags; |
52 | | static int hf_ziop_message_type; |
53 | | static int hf_ziop_message_size; |
54 | | static int hf_ziop_compressor_id; |
55 | | static int hf_ziop_original_length; |
56 | | |
57 | | static int ett_ziop; |
58 | | |
59 | | static expert_field ei_ziop_version; |
60 | | |
61 | | static dissector_handle_t ziop_tcp_handle; |
62 | | |
63 | | |
64 | | static const value_string ziop_compressor_ids[] = { |
65 | | { 0, "None" }, |
66 | | { 1, "GZIP"}, |
67 | | { 2, "PKZIP"}, |
68 | | { 3, "BZIP2"}, |
69 | | { 4, "ZLIB"}, |
70 | | { 5, "LZMA"}, |
71 | | { 6, "LZOP"}, |
72 | | { 7, "RZIP"}, |
73 | | { 8, "7X"}, |
74 | | { 9, "XAR"}, |
75 | | { 0, NULL} |
76 | | }; |
77 | | |
78 | | |
79 | | static const value_string giop_message_types[] = { |
80 | | { 0x0, "Request" }, |
81 | | { 0x1, "Reply"}, |
82 | | { 0x2, "CancelRequest"}, |
83 | | { 0x3, "LocateRequest"}, |
84 | | { 0x4, "LocateReply"}, |
85 | | { 0x5, "CloseConnection"}, |
86 | | { 0x6, "MessageError"}, |
87 | | { 0x7, "Fragment"}, |
88 | | { 0, NULL} |
89 | | }; |
90 | | |
91 | | |
92 | | static bool ziop_desegment = true; |
93 | | |
94 | | |
95 | | /* Main entry point */ |
96 | | static int |
97 | 83 | dissect_ziop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_) { |
98 | 83 | unsigned offset = 0; |
99 | 83 | uint8_t giop_version_major, giop_version_minor, message_type; |
100 | | |
101 | 83 | proto_tree *ziop_tree = NULL; |
102 | 83 | proto_item *ti; |
103 | 83 | uint8_t flags; |
104 | 83 | unsigned byte_order; |
105 | 83 | const char *label = "none"; |
106 | | |
107 | 83 | if (tvb_reported_length(tvb) < 7) |
108 | 0 | return 0; |
109 | | |
110 | 83 | col_set_str (pinfo->cinfo, COL_PROTOCOL, ZIOP_MAGIC); |
111 | | |
112 | | /* Clear out stuff in the info column */ |
113 | 83 | col_clear(pinfo->cinfo, COL_INFO); |
114 | | |
115 | 83 | ti = proto_tree_add_item (tree, proto_ziop, tvb, 0, -1, ENC_NA); |
116 | 83 | ziop_tree = proto_item_add_subtree (ti, ett_ziop); |
117 | | |
118 | 83 | proto_tree_add_item(ziop_tree, hf_ziop_magic, tvb, offset, 4, ENC_ASCII); |
119 | 83 | offset += 4; |
120 | 83 | proto_tree_add_item(ziop_tree, hf_ziop_giop_version_major, tvb, offset, 1, ENC_BIG_ENDIAN); |
121 | 83 | giop_version_major = tvb_get_uint8(tvb, offset); |
122 | 83 | offset++; |
123 | 83 | proto_tree_add_item(ziop_tree, hf_ziop_giop_version_minor, tvb, offset, 1, ENC_BIG_ENDIAN); |
124 | 83 | giop_version_minor = tvb_get_uint8(tvb, offset); |
125 | 83 | offset++; |
126 | | |
127 | 83 | if ( (giop_version_major < 1) || |
128 | 83 | (giop_version_minor < 2) ) /* earlier than GIOP 1.2 */ |
129 | 58 | { |
130 | 58 | col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u", |
131 | 58 | giop_version_major, giop_version_minor); |
132 | | |
133 | 58 | expert_add_info_format(pinfo, ti, &ei_ziop_version, |
134 | 58 | "Version %u.%u not supported", |
135 | 58 | giop_version_major, |
136 | 58 | giop_version_minor); |
137 | | |
138 | 58 | call_data_dissector(tvb, pinfo, tree); |
139 | 58 | return tvb_reported_length(tvb); |
140 | 58 | } |
141 | | |
142 | 25 | flags = tvb_get_uint8(tvb, offset); |
143 | 25 | byte_order = (flags & 0x01) ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN; |
144 | | |
145 | 25 | if (flags & 0x01) { |
146 | 10 | label = "little-endian"; |
147 | 10 | } |
148 | 25 | proto_tree_add_uint_format_value(ziop_tree, hf_ziop_flags, tvb, offset, 1, |
149 | 25 | flags, "0x%02x (%s)", flags, label); |
150 | 25 | offset++; |
151 | | |
152 | 25 | proto_tree_add_item(ziop_tree, hf_ziop_message_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
153 | 25 | message_type = tvb_get_uint8(tvb, offset); |
154 | 25 | offset++; |
155 | | |
156 | 25 | col_add_fstr (pinfo->cinfo, COL_INFO, "ZIOP %u.%u %s", |
157 | 25 | giop_version_major, |
158 | 25 | giop_version_minor, |
159 | 25 | val_to_str(message_type, giop_message_types, |
160 | 25 | "Unknown message type (0x%02x)") |
161 | 25 | ); |
162 | | |
163 | 25 | proto_tree_add_item(ziop_tree, hf_ziop_message_size, tvb, offset, 4, byte_order); |
164 | 25 | offset += 4; |
165 | 25 | proto_tree_add_item(ziop_tree, hf_ziop_compressor_id, tvb, offset, 2, byte_order); |
166 | 25 | offset += 4; |
167 | 25 | proto_tree_add_item(ziop_tree, hf_ziop_original_length, tvb, offset, 4, byte_order); |
168 | | |
169 | 25 | return tvb_reported_length(tvb); |
170 | 83 | } |
171 | | |
172 | | static unsigned |
173 | | get_ziop_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) |
174 | 87 | { |
175 | 87 | uint8_t flags; |
176 | 87 | unsigned message_size; |
177 | 87 | bool stream_is_big_endian; |
178 | | |
179 | 87 | if ( tvb_memeql(tvb, 0, (const uint8_t *)ZIOP_MAGIC, 4) != 0) |
180 | 0 | return 0; |
181 | | |
182 | 87 | flags = tvb_get_uint8(tvb, offset + 6); |
183 | | |
184 | 87 | stream_is_big_endian = ((flags & 0x1) == 0); |
185 | | |
186 | 87 | if (stream_is_big_endian) |
187 | 70 | message_size = tvb_get_ntohl(tvb, offset + 8); |
188 | 17 | else |
189 | 17 | message_size = tvb_get_letohl(tvb, offset + 8); |
190 | | |
191 | 87 | return message_size + ZIOP_HEADER_SIZE; |
192 | 87 | } |
193 | | |
194 | | static int |
195 | | dissect_ziop_tcp (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data) |
196 | 43 | { |
197 | 43 | if ( tvb_memeql(tvb, 0, (const uint8_t *)ZIOP_MAGIC, 4) != 0) |
198 | 24 | { |
199 | 24 | if (tvb_get_ntohl(tvb, 0) == GIOP_MAGIC_NUMBER) |
200 | 0 | { |
201 | 0 | dissect_giop(tvb, pinfo, tree); |
202 | 0 | return tvb_captured_length(tvb); |
203 | 0 | } |
204 | 24 | return 0; |
205 | 24 | } |
206 | | |
207 | 19 | tcp_dissect_pdus(tvb, pinfo, tree, ziop_desegment, ZIOP_HEADER_SIZE, |
208 | 19 | get_ziop_pdu_len, dissect_ziop, data); |
209 | 19 | return tvb_captured_length(tvb); |
210 | 43 | } |
211 | | |
212 | | |
213 | | bool |
214 | | dissect_ziop_heur (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data) |
215 | 2.37k | { |
216 | 2.37k | unsigned tot_len; |
217 | | |
218 | 2.37k | conversation_t *conversation; |
219 | | /* check magic number and version */ |
220 | | |
221 | 2.37k | tot_len = tvb_captured_length(tvb); |
222 | | |
223 | 2.37k | if (tot_len < ZIOP_HEADER_SIZE) /* tot_len < 12 */ |
224 | 286 | { |
225 | | /* Not enough data captured to hold the ZIOP header; don't try |
226 | | to interpret it as GIOP. */ |
227 | 286 | return false; |
228 | 286 | } |
229 | 2.09k | if ( tvb_memeql(tvb, 0, (const uint8_t *)ZIOP_MAGIC, 4) != 0) |
230 | 2.07k | { |
231 | 2.07k | return false; |
232 | 2.07k | } |
233 | | |
234 | 16 | if ( pinfo->ptype == PT_TCP ) |
235 | 16 | { |
236 | | /* |
237 | | * Make the ZIOP dissector the dissector for this conversation. |
238 | | * |
239 | | * If this isn't the first time this packet has been processed, |
240 | | * we've already done this work, so we don't need to do it |
241 | | * again. |
242 | | */ |
243 | 16 | if (!pinfo->fd->visited) |
244 | 16 | { |
245 | 16 | conversation = find_or_create_conversation(pinfo); |
246 | | |
247 | | /* Set dissector */ |
248 | 16 | conversation_set_dissector(conversation, ziop_tcp_handle); |
249 | 16 | } |
250 | 16 | dissect_ziop_tcp (tvb, pinfo, tree, data); |
251 | 16 | } |
252 | 0 | else |
253 | 0 | { |
254 | 0 | dissect_ziop (tvb, pinfo, tree, data); |
255 | 0 | } |
256 | 16 | return true; |
257 | 2.09k | } |
258 | | |
259 | | void |
260 | | proto_register_ziop (void) |
261 | 14 | { |
262 | | /* A header field is something you can search/filter on. |
263 | | * |
264 | | * We create a structure to register our fields. It consists of an |
265 | | * array of hf_register_info structures, each of which are of the format |
266 | | * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}. |
267 | | */ |
268 | 14 | static hf_register_info hf[] = { |
269 | 14 | { &hf_ziop_magic, |
270 | 14 | { "Header magic", "ziop.magic", FT_STRING, BASE_NONE, NULL, 0x0, |
271 | 14 | "ZIOPHeader magic", HFILL }}, |
272 | 14 | { &hf_ziop_giop_version_major, |
273 | 14 | { "Header major version", "ziop.giop_version_major", FT_UINT8, BASE_OCT, NULL, 0x0, |
274 | 14 | "ZIOPHeader giop_major_version", HFILL }}, |
275 | 14 | { &hf_ziop_giop_version_minor, |
276 | 14 | { "Header minor version", "ziop.giop_version_minor", FT_UINT8, BASE_OCT, NULL, 0x0, |
277 | 14 | "ZIOPHeader giop_minor_version", HFILL }}, |
278 | 14 | { &hf_ziop_flags, |
279 | 14 | { "Header flags", "ziop.flags", FT_UINT8, BASE_OCT, NULL, 0x0, |
280 | 14 | "ZIOPHeader flags", HFILL }}, |
281 | 14 | { &hf_ziop_message_type, |
282 | 14 | { "Header type", "ziop.message_type", FT_UINT8, BASE_OCT, VALS(giop_message_types), 0x0, |
283 | 14 | "ZIOPHeader message_type", HFILL }}, |
284 | 14 | { &hf_ziop_message_size, |
285 | 14 | { "Header size", "ziop.message_size", FT_UINT32, BASE_DEC, NULL, 0x0, |
286 | 14 | "ZIOPHeader message_size", HFILL }}, |
287 | 14 | { &hf_ziop_compressor_id, |
288 | 14 | { "Header compressor id", "ziop.compressor_id", FT_UINT16, BASE_DEC, VALS(ziop_compressor_ids), 0x0, |
289 | 14 | "ZIOPHeader compressor_id", HFILL }}, |
290 | 14 | { &hf_ziop_original_length, |
291 | 14 | { "Header original length", "ziop.original_length", FT_UINT32, BASE_DEC, NULL, 0x0, |
292 | 14 | "ZIOP original_length", HFILL }} |
293 | 14 | }; |
294 | | |
295 | 14 | static int *ett[] = { |
296 | 14 | &ett_ziop |
297 | 14 | }; |
298 | | |
299 | 14 | static ei_register_info ei[] = { |
300 | 14 | { &ei_ziop_version, { "ziop.version_not_supported", PI_PROTOCOL, PI_WARN, "Version not supported", EXPFILL }}, |
301 | 14 | }; |
302 | | |
303 | 14 | expert_module_t* expert_ziop; |
304 | | |
305 | 14 | proto_ziop = proto_register_protocol("Zipped Inter-ORB Protocol", "ZIOP", "ziop"); |
306 | 14 | proto_register_field_array (proto_ziop, hf, array_length (hf)); |
307 | 14 | proto_register_subtree_array (ett, array_length (ett)); |
308 | 14 | expert_ziop = expert_register_protocol(proto_ziop); |
309 | 14 | expert_register_field_array(expert_ziop, ei, array_length(ei)); |
310 | | |
311 | 14 | register_dissector("ziop", dissect_ziop, proto_ziop); |
312 | 14 | ziop_tcp_handle = register_dissector("ziop.tcp", dissect_ziop_tcp, proto_ziop); |
313 | 14 | } |
314 | | |
315 | | |
316 | | void |
317 | | proto_reg_handoff_ziop (void) |
318 | 14 | { |
319 | 14 | dissector_add_for_decode_as_with_preference("udp.port", ziop_tcp_handle); |
320 | | |
321 | 14 | heur_dissector_add("tcp", dissect_ziop_heur, "ZIOP over TCP", "ziop_tcp", proto_ziop, HEURISTIC_ENABLE); |
322 | 14 | } |
323 | | |
324 | | /* |
325 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
326 | | * |
327 | | * Local variables: |
328 | | * c-basic-offset: 2 |
329 | | * tab-width: 8 |
330 | | * indent-tabs-mode: nil |
331 | | * End: |
332 | | * |
333 | | * vi: set shiftwidth=2 tabstop=8 expandtab: |
334 | | * :indentSize=2:tabSize=8:noTabs=true: |
335 | | */ |