/src/wireshark/epan/dissectors/packet-monero.c
Line | Count | Source |
1 | | /* packet-monero.c |
2 | | * Routines for Monero protocol dissection |
3 | | * Copyright 2023, snicket2100 <snicket2100@protonmail.com> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | #include "config.h" |
12 | | |
13 | | #include <epan/packet.h> |
14 | | #include <epan/tfs.h> |
15 | | #include <wsutil/array.h> |
16 | | #include <epan/prefs.h> |
17 | | #include <epan/expert.h> |
18 | | |
19 | | #include "packet-tcp.h" |
20 | | |
21 | 2.49k | #define MONERO_LEVIN_SIGNATURE 0x0101010101012101 |
22 | | #define MONERO_PAYLOAD_MAGIC 0x011101010101020101 |
23 | 85 | #define MONERO_PAYLOAD_TYPE_INT64 1 |
24 | 237 | #define MONERO_PAYLOAD_TYPE_INT32 2 |
25 | 248 | #define MONERO_PAYLOAD_TYPE_INT16 3 |
26 | 207 | #define MONERO_PAYLOAD_TYPE_INT8 4 |
27 | 56 | #define MONERO_PAYLOAD_TYPE_UINT64 5 |
28 | 37 | #define MONERO_PAYLOAD_TYPE_UINT32 6 |
29 | 4 | #define MONERO_PAYLOAD_TYPE_UINT16 7 |
30 | 883 | #define MONERO_PAYLOAD_TYPE_UINT8 8 |
31 | 26 | #define MONERO_PAYLOAD_TYPE_FLOAT64 9 |
32 | 2.17k | #define MONERO_PAYLOAD_TYPE_STRING 10 |
33 | 0 | #define MONERO_PAYLOAD_TYPE_BOOLEAN 11 |
34 | 4 | #define MONERO_PAYLOAD_TYPE_STRUCT 12 |
35 | 2.09k | #define MONERO_PAYLOAD_ARRAY 0x80 |
36 | | |
37 | | static const value_string monero_commands[] = |
38 | | { |
39 | | { 1001, "Handshake" }, |
40 | | { 1002, "TimedSync" }, |
41 | | { 1003, "Ping" }, |
42 | | { 1007, "SupportFlags" }, |
43 | | { 2001, "NewBlock" }, |
44 | | { 2002, "NewTransactions" }, |
45 | | { 2003, "GetObjectsRequest" }, |
46 | | { 2004, "GetObjectsResponse" }, |
47 | | { 2006, "ChainRequest" }, |
48 | | { 2007, "ChainResponse" }, |
49 | | { 2008, "NewFluffyBlock" }, |
50 | | { 2009, "FluffyMissingTxsRequest" }, |
51 | | { 2010, "GetTxPoolComplement" }, |
52 | | { 2011, "TxPoolHash" }, |
53 | | { 2012, "RequestTxPoolTxs" }, |
54 | | { 0, NULL } |
55 | | }; |
56 | | |
57 | | static const value_string payload_types[] = |
58 | | { |
59 | | { MONERO_PAYLOAD_TYPE_INT64, "int64" }, |
60 | | { MONERO_PAYLOAD_TYPE_INT32, "int32" }, |
61 | | { MONERO_PAYLOAD_TYPE_INT16, "int16" }, |
62 | | { MONERO_PAYLOAD_TYPE_INT8, "int8" }, |
63 | | { MONERO_PAYLOAD_TYPE_UINT64, "uint64" }, |
64 | | { MONERO_PAYLOAD_TYPE_UINT32, "uint32" }, |
65 | | { MONERO_PAYLOAD_TYPE_UINT16, "uint16" }, |
66 | | { MONERO_PAYLOAD_TYPE_UINT8, "uint8" }, |
67 | | { MONERO_PAYLOAD_TYPE_FLOAT64, "float64" }, |
68 | | { MONERO_PAYLOAD_TYPE_STRING, "string" }, |
69 | | { MONERO_PAYLOAD_TYPE_BOOLEAN, "boolean" }, |
70 | | { MONERO_PAYLOAD_TYPE_STRUCT, "struct" }, |
71 | | |
72 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_INT64, "array[int64]" }, |
73 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_INT32, "array[int32]" }, |
74 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_INT16, "array[int16]" }, |
75 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_INT8, "array[int8]" }, |
76 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_UINT64, "array[uint64]" }, |
77 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_UINT32, "array[uint32]" }, |
78 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_UINT16, "array[uint16]" }, |
79 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_UINT8, "array[uint8]" }, |
80 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_FLOAT64, "array[float64]" }, |
81 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_STRING, "array[string]" }, |
82 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_BOOLEAN, "array[boolean]" }, |
83 | | { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_STRUCT, "array[struct]" }, |
84 | | |
85 | | { 0, NULL } |
86 | | }; |
87 | | |
88 | | /* |
89 | | * Monero message header. |
90 | | * - Network signature - 8 bytes |
91 | | * - Body size - 8 bytes |
92 | | * - Have to return data - 1 byte |
93 | | * - Command - 4 bytes |
94 | | * - Return code - 4 bytes |
95 | | * - Flags - 4 bytes |
96 | | * - Protocol version - 4 bytes |
97 | | */ |
98 | 259 | #define MONERO_HEADER_LENGTH 8+8+1+4+4+4+4 |
99 | | |
100 | | void proto_register_monero(void); |
101 | | void proto_reg_handoff_monero(void); |
102 | | |
103 | | static dissector_handle_t monero_handle; |
104 | | |
105 | | static int proto_monero; |
106 | | |
107 | | static int hf_monero_signature; |
108 | | static int hf_monero_length; |
109 | | static int hf_monero_havetoreturn; |
110 | | static int hf_monero_command; |
111 | | static int hf_monero_return_code; |
112 | | static int hf_monero_flags; |
113 | | static int hf_monero_flags_request; |
114 | | static int hf_monero_flags_response; |
115 | | static int hf_monero_flags_start_fragment; |
116 | | static int hf_monero_flags_end_fragment; |
117 | | static int hf_monero_flags_reserved; |
118 | | static int hf_monero_protocol; |
119 | | static int hf_monero_payload; |
120 | | static int hf_monero_payload_magic; |
121 | | static int hf_monero_payload_item; |
122 | | static int hf_monero_payload_item_key; |
123 | | static int hf_monero_payload_item_type; |
124 | | static int hf_monero_payload_item_size; |
125 | | static int hf_monero_payload_item_length; |
126 | | static int hf_monero_payload_item_value_int8; |
127 | | static int hf_monero_payload_item_value_int16; |
128 | | static int hf_monero_payload_item_value_int32; |
129 | | static int hf_monero_payload_item_value_int64; |
130 | | static int hf_monero_payload_item_value_uint8; |
131 | | static int hf_monero_payload_item_value_uint16; |
132 | | static int hf_monero_payload_item_value_uint32; |
133 | | static int hf_monero_payload_item_value_uint64; |
134 | | static int hf_monero_payload_item_value_float64; |
135 | | static int hf_monero_payload_item_value_string; |
136 | | static int hf_monero_payload_item_value_boolean; |
137 | | static int hf_monero_payload_item_value_struct; |
138 | | static int hf_monero_payload_item_value_array; |
139 | | |
140 | | static int * const flags_hf_flags[] = { |
141 | | &hf_monero_flags_request, |
142 | | &hf_monero_flags_response, |
143 | | &hf_monero_flags_start_fragment, |
144 | | &hf_monero_flags_end_fragment, |
145 | | &hf_monero_flags_reserved, |
146 | | NULL |
147 | | }; |
148 | | |
149 | | static int ett_monero; |
150 | | static int ett_payload; |
151 | | static int ett_struct; |
152 | | static int ett_flags; |
153 | | |
154 | | static bool monero_desegment = true; |
155 | | |
156 | | static expert_field ei_monero_type_unknown; |
157 | | |
158 | | static unsigned |
159 | | get_monero_pdu_length(packet_info *pinfo _U_, tvbuff_t *tvb, |
160 | | int offset, void *data _U_) |
161 | 94 | { |
162 | 94 | unsigned length; |
163 | 94 | length = MONERO_HEADER_LENGTH; |
164 | | |
165 | | /* add payload length */ |
166 | 94 | length += (unsigned)tvb_get_letoh64(tvb, offset+8); |
167 | | |
168 | 94 | return length; |
169 | 94 | } |
170 | | |
171 | | static void |
172 | | get_varint(tvbuff_t *tvb, const int offset, uint8_t *length, uint64_t *ret) |
173 | 349 | { |
174 | 349 | uint8_t flag = tvb_get_uint8(tvb, offset) & 0x03; |
175 | | |
176 | 349 | switch (flag) |
177 | 349 | { |
178 | 204 | case 0: |
179 | 204 | *ret = tvb_get_uint8(tvb, offset) >> 2; |
180 | 204 | *length = 1; |
181 | 204 | break; |
182 | 41 | case 1: |
183 | 41 | *ret = tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN) >> 2; |
184 | 41 | *length = 2; |
185 | 41 | break; |
186 | 29 | case 2: |
187 | 29 | *ret = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN) >> 2; |
188 | 29 | *length = 4; |
189 | 29 | break; |
190 | 75 | case 3: |
191 | 75 | *ret = tvb_get_uint64(tvb, offset, ENC_LITTLE_ENDIAN) >> 2; |
192 | 75 | *length = 8; |
193 | 75 | break; |
194 | 349 | } |
195 | 349 | } |
196 | | |
197 | | static int dissect_encoded_value(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, proto_item *ti, int offset, uint32_t type); |
198 | | |
199 | | // we check for recursion limits due to nested structs |
200 | | // NOLINTNEXTLINE(misc-no-recursion) |
201 | | static int dissect_encoded_dictionary(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset) |
202 | 80 | { |
203 | 80 | uint8_t length; |
204 | 80 | uint64_t count; |
205 | 80 | proto_item *sti; |
206 | 80 | proto_tree *stree; |
207 | 80 | uint32_t type; |
208 | 80 | const uint8_t* key; |
209 | | |
210 | | // number of keys in the dictionary |
211 | 80 | get_varint(tvb, offset, &length, &count); |
212 | 80 | offset += length; |
213 | | |
214 | 255 | for (; count > 0; count--) |
215 | 175 | { |
216 | 175 | sti = proto_tree_add_item(tree, hf_monero_payload_item, tvb, offset, -1, ENC_NA); |
217 | 175 | stree = proto_item_add_subtree(sti, ett_payload); |
218 | | |
219 | | // key |
220 | 175 | length = tvb_get_uint8(tvb, offset); |
221 | 175 | offset += 1; |
222 | 175 | proto_tree_add_item_ret_string(stree, hf_monero_payload_item_key, tvb, offset, length, ENC_ASCII|ENC_NA, pinfo->pool, &key); |
223 | 175 | if(key) |
224 | 140 | proto_item_set_text(sti, "%s", key); |
225 | 175 | offset += length; |
226 | | |
227 | | // type |
228 | 175 | proto_tree_add_item_ret_uint(stree, hf_monero_payload_item_type, tvb, offset, 1, ENC_NA, &type); |
229 | 175 | offset += 1; |
230 | | |
231 | | // value |
232 | 175 | offset = dissect_encoded_value(tvb, pinfo, stree, sti, offset, type); |
233 | | |
234 | 175 | proto_item_set_end(sti, tvb, offset); |
235 | 175 | } |
236 | | |
237 | 80 | return offset; |
238 | 80 | } |
239 | | |
240 | | // we check for recursion limits due to nested structs |
241 | | // NOLINTNEXTLINE(misc-no-recursion) |
242 | | static int dissect_encoded_value(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, proto_item *ti, int offset, uint32_t type) |
243 | 2.08k | { |
244 | 2.08k | uint8_t length; |
245 | 2.08k | uint64_t size; |
246 | 2.08k | uint64_t string_length; |
247 | 2.08k | proto_item *struct_ti; |
248 | 2.08k | proto_tree *struct_tree; |
249 | | |
250 | 2.08k | if (!try_val_to_str(type, payload_types)) { |
251 | | /* The type is used to determine the length of the value; if it's unknown |
252 | | * then we can't dissect any further. (In particular, this keeps from |
253 | | * looping repeatedly on invalid arrays.) |
254 | | */ |
255 | 27 | expert_add_info(pinfo, ti, &ei_monero_type_unknown); |
256 | 27 | return tvb_reported_length(tvb); |
257 | 27 | } |
258 | | |
259 | | // array of values |
260 | 2.05k | if (type & MONERO_PAYLOAD_ARRAY) { |
261 | 43 | get_varint(tvb, offset, &length, &size); |
262 | 43 | proto_tree_add_int64(tree, hf_monero_payload_item_size, tvb, offset, length, size); |
263 | 43 | offset += length; |
264 | | |
265 | 43 | type -= MONERO_PAYLOAD_ARRAY; |
266 | | |
267 | 1.98k | for (; size > 0; size--) { |
268 | 1.94k | if (type == MONERO_PAYLOAD_TYPE_STRING) { |
269 | 228 | struct_ti = proto_tree_add_item(tree, hf_monero_payload_item_value_array, tvb, offset, -1, ENC_NA); |
270 | 228 | struct_tree = proto_item_add_subtree(struct_ti, ett_struct); |
271 | | |
272 | 228 | offset = dissect_encoded_value(tvb, pinfo, struct_tree, ti, offset, type); |
273 | | |
274 | 228 | proto_item_set_end(struct_ti, tvb, offset); |
275 | 228 | } |
276 | 1.71k | else { |
277 | 1.71k | offset = dissect_encoded_value(tvb, pinfo, tree, ti, offset, type); |
278 | 1.71k | } |
279 | 1.94k | } |
280 | 43 | return offset; |
281 | 43 | } |
282 | | |
283 | 2.01k | switch (type) |
284 | 2.01k | { |
285 | 85 | case MONERO_PAYLOAD_TYPE_INT64: |
286 | 85 | proto_tree_add_item(tree, hf_monero_payload_item_value_int64, tvb, offset, 8, ENC_LITTLE_ENDIAN); |
287 | 85 | offset += 8; |
288 | 85 | break; |
289 | | |
290 | 237 | case MONERO_PAYLOAD_TYPE_INT32: |
291 | 237 | proto_tree_add_item(tree, hf_monero_payload_item_value_int32, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
292 | 237 | offset += 4; |
293 | 237 | break; |
294 | | |
295 | 248 | case MONERO_PAYLOAD_TYPE_INT16: |
296 | 248 | proto_tree_add_item(tree, hf_monero_payload_item_value_int16, tvb, offset, 2, ENC_LITTLE_ENDIAN); |
297 | 248 | offset += 2; |
298 | 248 | break; |
299 | | |
300 | 207 | case MONERO_PAYLOAD_TYPE_INT8: |
301 | 207 | proto_tree_add_item(tree, hf_monero_payload_item_value_int8, tvb, offset, 1, ENC_LITTLE_ENDIAN); |
302 | 207 | offset += 1; |
303 | 207 | break; |
304 | | |
305 | 56 | case MONERO_PAYLOAD_TYPE_UINT64: |
306 | 56 | proto_tree_add_item(tree, hf_monero_payload_item_value_uint64, tvb, offset, 8, ENC_LITTLE_ENDIAN); |
307 | 56 | offset += 8; |
308 | 56 | break; |
309 | | |
310 | 37 | case MONERO_PAYLOAD_TYPE_UINT32: |
311 | 37 | proto_tree_add_item(tree, hf_monero_payload_item_value_uint32, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
312 | 37 | offset += 4; |
313 | 37 | break; |
314 | | |
315 | 4 | case MONERO_PAYLOAD_TYPE_UINT16: |
316 | 4 | proto_tree_add_item(tree, hf_monero_payload_item_value_uint16, tvb, offset, 2, ENC_LITTLE_ENDIAN); |
317 | 4 | offset += 2; |
318 | 4 | break; |
319 | | |
320 | 883 | case MONERO_PAYLOAD_TYPE_UINT8: |
321 | 883 | proto_tree_add_item(tree, hf_monero_payload_item_value_uint8, tvb, offset, 1, ENC_LITTLE_ENDIAN); |
322 | 883 | offset += 1; |
323 | 883 | break; |
324 | | |
325 | 26 | case MONERO_PAYLOAD_TYPE_FLOAT64: |
326 | 26 | proto_tree_add_item(tree, hf_monero_payload_item_value_float64, tvb, offset, 8, ENC_LITTLE_ENDIAN); |
327 | 26 | offset += 8; |
328 | 26 | break; |
329 | | |
330 | 226 | case MONERO_PAYLOAD_TYPE_STRING: |
331 | 226 | get_varint(tvb, offset, &length, &string_length); |
332 | 226 | proto_tree_add_int64(tree, hf_monero_payload_item_length, tvb, offset, length, string_length); |
333 | 226 | offset += length; |
334 | | |
335 | 226 | proto_tree_add_item(tree, hf_monero_payload_item_value_string, tvb, offset, (int) string_length, ENC_NA); |
336 | 226 | offset += (int)string_length; |
337 | 226 | break; |
338 | | |
339 | 0 | case MONERO_PAYLOAD_TYPE_BOOLEAN: |
340 | 0 | proto_tree_add_item(tree, hf_monero_payload_item_value_int64, tvb, offset, 1, ENC_LITTLE_ENDIAN); |
341 | 0 | offset += 1; |
342 | 0 | break; |
343 | | |
344 | 4 | case MONERO_PAYLOAD_TYPE_STRUCT: |
345 | 4 | struct_ti = proto_tree_add_item(tree, hf_monero_payload_item_value_struct, tvb, offset, -1, ENC_NA); |
346 | 4 | struct_tree = proto_item_add_subtree(struct_ti, ett_struct); |
347 | | |
348 | 4 | increment_dissection_depth_by_n(pinfo, 2); |
349 | 4 | offset = dissect_encoded_dictionary(tvb, pinfo, struct_tree, offset); |
350 | 4 | decrement_dissection_depth_by_n(pinfo, 2); |
351 | 4 | proto_item_set_end(struct_ti, tvb, offset); |
352 | 4 | break; |
353 | | |
354 | 0 | default: |
355 | 0 | expert_add_info(pinfo, ti, &ei_monero_type_unknown); |
356 | 0 | offset = tvb_reported_length(tvb); |
357 | 0 | break; |
358 | 2.01k | } |
359 | | |
360 | 1.97k | return offset; |
361 | 2.01k | } |
362 | | |
363 | | static void dissect_encoded_payload(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree) |
364 | 92 | { |
365 | 92 | proto_tree_add_item(tree, hf_monero_payload_magic, tvb, 0, 9, ENC_NA); |
366 | 92 | dissect_encoded_dictionary(tvb, pinfo, tree, 9); |
367 | 92 | } |
368 | | |
369 | | static int dissect_monero_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
370 | 93 | { |
371 | 93 | proto_item *ti, *payload_ti; |
372 | 93 | proto_tree *payload_tree; |
373 | 93 | uint32_t command; |
374 | 93 | const char* command_label; |
375 | 93 | uint64_t length; |
376 | 93 | uint32_t offset = 0; |
377 | | |
378 | 93 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "Monero"); |
379 | | |
380 | 93 | ti = proto_tree_add_item(tree, proto_monero, tvb, 0, -1, ENC_NA); |
381 | 93 | tree = proto_item_add_subtree(ti, ett_monero); |
382 | | |
383 | | /* header fields */ |
384 | 93 | proto_tree_add_item(tree, hf_monero_signature, tvb, 0, 8, ENC_BIG_ENDIAN); |
385 | 93 | proto_tree_add_item_ret_uint64(tree, hf_monero_length, tvb, 8, 8, ENC_LITTLE_ENDIAN, &length); |
386 | 93 | proto_tree_add_item(tree, hf_monero_havetoreturn, tvb, 16, 1, ENC_LITTLE_ENDIAN); |
387 | 93 | proto_tree_add_item_ret_uint(tree, hf_monero_command, tvb, 17, 4, ENC_LITTLE_ENDIAN, &command); |
388 | 93 | proto_tree_add_item(tree, hf_monero_return_code, tvb, 21, 4, ENC_LITTLE_ENDIAN); |
389 | 93 | proto_tree_add_bitmask(tree, tvb, 25, hf_monero_flags, ett_flags, flags_hf_flags, ENC_LITTLE_ENDIAN); |
390 | 93 | proto_tree_add_item(tree, hf_monero_protocol, tvb, 29, 4, ENC_LITTLE_ENDIAN); |
391 | 93 | offset += MONERO_HEADER_LENGTH; |
392 | | |
393 | 93 | command_label = val_to_str(pinfo->pool, command, monero_commands, "[Unknown command %d]"); |
394 | 93 | col_add_str(pinfo->cinfo, COL_INFO, command_label); |
395 | | |
396 | | /* data payload */ |
397 | 93 | payload_ti = proto_tree_add_item(tree, hf_monero_payload, tvb, offset, (int) length, ENC_NA); |
398 | 93 | payload_tree = proto_item_add_subtree(payload_ti, ett_payload); |
399 | 93 | dissect_encoded_payload(tvb_new_subset_length(tvb, offset, (int) length), pinfo, payload_tree); |
400 | | // offset += size; |
401 | | |
402 | 93 | return tvb_reported_length(tvb); |
403 | 93 | } |
404 | | |
405 | | static int |
406 | | dissect_monero(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
407 | 72 | { |
408 | 72 | col_clear(pinfo->cinfo, COL_INFO); |
409 | 72 | tcp_dissect_pdus(tvb, pinfo, tree, monero_desegment, MONERO_HEADER_LENGTH, |
410 | 72 | get_monero_pdu_length, dissect_monero_tcp_pdu, data); |
411 | | |
412 | 72 | return tvb_reported_length(tvb); |
413 | 72 | } |
414 | | |
415 | | static bool |
416 | | dissect_monero_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
417 | 2.71k | { |
418 | 2.71k | uint64_t signature; |
419 | 2.71k | conversation_t *conversation; |
420 | | |
421 | 2.71k | if (tvb_captured_length(tvb) < 8) |
422 | 220 | return false; |
423 | | |
424 | 2.49k | signature = tvb_get_letoh64(tvb, 0); |
425 | 2.49k | if (signature != MONERO_LEVIN_SIGNATURE) |
426 | 2.44k | return false; |
427 | | |
428 | | /* Ok: This connection should always use the monero dissector */ |
429 | 52 | conversation = find_or_create_conversation(pinfo); |
430 | 52 | conversation_set_dissector(conversation, monero_handle); |
431 | | |
432 | 52 | dissect_monero(tvb, pinfo, tree, data); |
433 | 52 | return true; |
434 | 2.49k | } |
435 | | |
436 | | void |
437 | | proto_register_monero(void) |
438 | 16 | { |
439 | 16 | static hf_register_info hf[] = { |
440 | 16 | { &hf_monero_signature, |
441 | 16 | { "Signature", "monero.signature", |
442 | 16 | FT_UINT64, BASE_HEX, NULL, 0x0, |
443 | 16 | NULL, HFILL } |
444 | 16 | }, |
445 | 16 | { &hf_monero_length, |
446 | 16 | { "Payload Length", "monero.length", |
447 | 16 | FT_UINT64, BASE_DEC, NULL, 0x0, |
448 | 16 | NULL, HFILL } |
449 | 16 | }, |
450 | 16 | { &hf_monero_havetoreturn, |
451 | 16 | { "Have to return data", "monero.have_to_return_data", |
452 | 16 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
453 | 16 | NULL, HFILL } |
454 | 16 | }, |
455 | 16 | { &hf_monero_command, |
456 | 16 | { "Command", "monero.command", |
457 | 16 | FT_UINT32, BASE_DEC, VALS(monero_commands), 0x0, |
458 | 16 | NULL, HFILL } |
459 | 16 | }, |
460 | 16 | { &hf_monero_return_code, |
461 | 16 | { "Return Code", "monero.return_code", |
462 | 16 | FT_INT32, BASE_DEC, NULL, 0x0, |
463 | 16 | NULL, HFILL } |
464 | 16 | }, |
465 | 16 | { &hf_monero_flags, |
466 | 16 | { "Flags", "monero.flags", |
467 | 16 | FT_UINT32, BASE_DEC, NULL, 0x0, |
468 | 16 | NULL, HFILL } |
469 | 16 | }, |
470 | 16 | { &hf_monero_flags_request, |
471 | 16 | { "Request", "monero.flags.request", |
472 | 16 | FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000001, |
473 | 16 | NULL, HFILL } |
474 | 16 | }, |
475 | 16 | { &hf_monero_flags_response, |
476 | 16 | { "Response", "monero.flags.response", |
477 | 16 | FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000002, |
478 | 16 | NULL, HFILL } |
479 | 16 | }, |
480 | 16 | { &hf_monero_flags_start_fragment, |
481 | 16 | { "Start fragment", "monero.flags.start_fragment", |
482 | 16 | FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000004, |
483 | 16 | NULL, HFILL } |
484 | 16 | }, |
485 | 16 | { &hf_monero_flags_end_fragment, |
486 | 16 | { "End fragment", "monero.flags.end_fragment", |
487 | 16 | FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000008, |
488 | 16 | NULL, HFILL } |
489 | 16 | }, |
490 | 16 | { &hf_monero_flags_reserved, |
491 | 16 | { "Reserved", "monero.flags.reserved", |
492 | 16 | FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0xfffffff0, |
493 | 16 | NULL, HFILL } |
494 | 16 | }, |
495 | 16 | { &hf_monero_protocol, |
496 | 16 | { "Protocol version", "monero.version", |
497 | 16 | FT_UINT32, BASE_DEC, NULL, 0x0, |
498 | 16 | NULL, HFILL } |
499 | 16 | }, |
500 | 16 | { &hf_monero_payload, |
501 | 16 | { "Payload", "monero.payload", |
502 | 16 | FT_NONE, BASE_NONE, NULL, 0x0, |
503 | 16 | NULL, HFILL } |
504 | 16 | }, |
505 | 16 | { &hf_monero_payload_magic, |
506 | 16 | { "Magic number", "monero.payload.magic", |
507 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
508 | 16 | NULL, HFILL } |
509 | 16 | }, |
510 | 16 | { &hf_monero_payload_item, |
511 | 16 | { "Entry", "monero.payload.item", |
512 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
513 | 16 | NULL, HFILL } |
514 | 16 | }, |
515 | 16 | { &hf_monero_payload_item_key, |
516 | 16 | { "Key", "monero.payload.item.key", |
517 | 16 | FT_STRING, BASE_NONE, NULL, 0x0, |
518 | 16 | NULL, HFILL } |
519 | 16 | }, |
520 | 16 | { &hf_monero_payload_item_type, |
521 | 16 | { "Type", "monero.payload.item.type", |
522 | 16 | FT_UINT8, BASE_DEC, VALS(payload_types), 0x0, |
523 | 16 | NULL, HFILL } |
524 | 16 | }, |
525 | 16 | { &hf_monero_payload_item_size, |
526 | 16 | { "Size", "monero.payload.item.size", |
527 | 16 | FT_INT64, BASE_DEC, NULL, 0x0, |
528 | 16 | NULL, HFILL } |
529 | 16 | }, |
530 | 16 | { &hf_monero_payload_item_length, |
531 | 16 | { "Length", "monero.payload.item.length", |
532 | 16 | FT_INT64, BASE_DEC, NULL, 0x0, |
533 | 16 | NULL, HFILL } |
534 | 16 | }, |
535 | 16 | { &hf_monero_payload_item_value_int8, |
536 | 16 | { "Value", "monero.payload.item.value.int8", |
537 | 16 | FT_INT8, BASE_DEC, NULL, 0x0, |
538 | 16 | NULL, HFILL } |
539 | 16 | }, |
540 | 16 | { &hf_monero_payload_item_value_int16, |
541 | 16 | { "Value", "monero.payload.item.value.int16", |
542 | 16 | FT_INT16, BASE_DEC, NULL, 0x0, |
543 | 16 | NULL, HFILL } |
544 | 16 | }, |
545 | 16 | { &hf_monero_payload_item_value_int32, |
546 | 16 | { "Value", "monero.payload.item.value.int32", |
547 | 16 | FT_INT32, BASE_DEC, NULL, 0x0, |
548 | 16 | NULL, HFILL } |
549 | 16 | }, |
550 | 16 | { &hf_monero_payload_item_value_int64, |
551 | 16 | { "Value", "monero.payload.item.value.int64", |
552 | 16 | FT_INT64, BASE_DEC, NULL, 0x0, |
553 | 16 | NULL, HFILL } |
554 | 16 | }, |
555 | 16 | { &hf_monero_payload_item_value_uint8, |
556 | 16 | { "Value", "monero.payload.item.value.uint8", |
557 | 16 | FT_UINT8, BASE_DEC, NULL, 0x0, |
558 | 16 | NULL, HFILL } |
559 | 16 | }, |
560 | 16 | { &hf_monero_payload_item_value_uint16, |
561 | 16 | { "Value", "monero.payload.item.value.uint16", |
562 | 16 | FT_UINT16, BASE_DEC, NULL, 0x0, |
563 | 16 | NULL, HFILL } |
564 | 16 | }, |
565 | 16 | { &hf_monero_payload_item_value_uint32, |
566 | 16 | { "Value", "monero.payload.item.value.uint32", |
567 | 16 | FT_UINT32, BASE_DEC, NULL, 0x0, |
568 | 16 | NULL, HFILL } |
569 | 16 | }, |
570 | 16 | { &hf_monero_payload_item_value_uint64, |
571 | 16 | { "Value", "monero.payload.item.value.uint64", |
572 | 16 | FT_UINT64, BASE_DEC, NULL, 0x0, |
573 | 16 | NULL, HFILL } |
574 | 16 | }, |
575 | 16 | { &hf_monero_payload_item_value_float64, |
576 | 16 | { "Value", "monero.payload.item.value.float64", |
577 | 16 | FT_DOUBLE, BASE_DEC, NULL, 0x0, |
578 | 16 | NULL, HFILL } |
579 | 16 | }, |
580 | 16 | { &hf_monero_payload_item_value_string, |
581 | 16 | { "Value", "monero.payload.item.value.string", |
582 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
583 | 16 | NULL, HFILL } |
584 | 16 | }, |
585 | 16 | { &hf_monero_payload_item_value_boolean, |
586 | 16 | { "Value", "monero.payload.item.value.boolean", |
587 | 16 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
588 | 16 | NULL, HFILL } |
589 | 16 | }, |
590 | 16 | { &hf_monero_payload_item_value_struct, |
591 | 16 | { "Value", "monero.payload.item.value.struct", |
592 | 16 | FT_NONE, BASE_NONE, NULL, 0x0, |
593 | 16 | NULL, HFILL } |
594 | 16 | }, |
595 | 16 | { &hf_monero_payload_item_value_array, |
596 | 16 | { "Value", "monero.payload.item.value.array", |
597 | 16 | FT_NONE, BASE_NONE, NULL, 0x0, |
598 | 16 | NULL, HFILL } |
599 | 16 | }, |
600 | 16 | }; |
601 | | |
602 | 16 | static int *ett[] = { |
603 | 16 | &ett_monero, |
604 | 16 | &ett_payload, |
605 | 16 | &ett_struct, |
606 | 16 | &ett_flags, |
607 | 16 | }; |
608 | | |
609 | 16 | module_t *monero_module; |
610 | 16 | expert_module_t* expert_monero; |
611 | | |
612 | 16 | proto_monero = proto_register_protocol("Monero protocol", "Monero", "monero"); |
613 | | |
614 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
615 | 16 | proto_register_field_array(proto_monero, hf, array_length(hf)); |
616 | | |
617 | 16 | static ei_register_info ei[] = { |
618 | 16 | { &ei_monero_type_unknown, { "monero.payload.item.type.unknown", PI_PROTOCOL, PI_WARN, "Unknown type", EXPFILL }}, |
619 | 16 | }; |
620 | | |
621 | 16 | expert_monero = expert_register_protocol(proto_monero); |
622 | 16 | expert_register_field_array(expert_monero, ei, array_length(ei)); |
623 | | |
624 | 16 | monero_handle = register_dissector("monero", dissect_monero, proto_monero); |
625 | | |
626 | 16 | monero_module = prefs_register_protocol(proto_monero, NULL); |
627 | 16 | prefs_register_bool_preference(monero_module, "desegment", |
628 | 16 | "Desegment all Monero messages spanning multiple TCP segments", |
629 | 16 | "Whether the Monero dissector should desegment all messages" |
630 | 16 | " spanning multiple TCP segments", |
631 | 16 | &monero_desegment); |
632 | | |
633 | 16 | } |
634 | | |
635 | | void |
636 | | proto_reg_handoff_monero(void) |
637 | 16 | { |
638 | 16 | dissector_add_for_decode_as_with_preference("tcp.port", monero_handle); |
639 | | |
640 | 16 | heur_dissector_add( "tcp", dissect_monero_heur, "Monero over TCP", "monero_tcp", proto_monero, HEURISTIC_ENABLE); |
641 | 16 | } |
642 | | |
643 | | /* |
644 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
645 | | * |
646 | | * Local variables: |
647 | | * c-basic-offset: 2 |
648 | | * tab-width: 8 |
649 | | * indent-tabs-mode: nil |
650 | | * End: |
651 | | * |
652 | | * vi: set shiftwidth=2 tabstop=8 expandtab: |
653 | | * :indentSize=2:tabSize=8:noTabs=true: |
654 | | */ |