Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-monero.c
blob772705acfcdcc5788044b9326af78952cc24a845
1 /* packet-monero.c
2 * Routines for Monero protocol dissection
3 * Copyright 2023, snicket2100 <snicket2100@protonmail.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
11 #include "config.h"
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>
19 #include "packet-tcp.h"
21 #define MONERO_LEVIN_SIGNATURE 0x0101010101012101
22 #define MONERO_PAYLOAD_MAGIC 0x011101010101020101
23 #define MONERO_PAYLOAD_TYPE_INT64 1
24 #define MONERO_PAYLOAD_TYPE_INT32 2
25 #define MONERO_PAYLOAD_TYPE_INT16 3
26 #define MONERO_PAYLOAD_TYPE_INT8 4
27 #define MONERO_PAYLOAD_TYPE_UINT64 5
28 #define MONERO_PAYLOAD_TYPE_UINT32 6
29 #define MONERO_PAYLOAD_TYPE_UINT16 7
30 #define MONERO_PAYLOAD_TYPE_UINT8 8
31 #define MONERO_PAYLOAD_TYPE_FLOAT64 9
32 #define MONERO_PAYLOAD_TYPE_STRING 10
33 #define MONERO_PAYLOAD_TYPE_BOOLEAN 11
34 #define MONERO_PAYLOAD_TYPE_STRUCT 12
35 #define MONERO_PAYLOAD_ARRAY 0x80
37 static const value_string monero_commands[] =
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, "GetTxPoolCompliment" },
52 { 0, NULL }
55 static const value_string payload_types[] =
57 { MONERO_PAYLOAD_TYPE_INT64, "int64" },
58 { MONERO_PAYLOAD_TYPE_INT32, "int32" },
59 { MONERO_PAYLOAD_TYPE_INT16, "int16" },
60 { MONERO_PAYLOAD_TYPE_INT8, "int8" },
61 { MONERO_PAYLOAD_TYPE_UINT64, "uint64" },
62 { MONERO_PAYLOAD_TYPE_UINT32, "uint32" },
63 { MONERO_PAYLOAD_TYPE_UINT16, "uint16" },
64 { MONERO_PAYLOAD_TYPE_UINT8, "uint8" },
65 { MONERO_PAYLOAD_TYPE_FLOAT64, "float64" },
66 { MONERO_PAYLOAD_TYPE_STRING, "string" },
67 { MONERO_PAYLOAD_TYPE_BOOLEAN, "boolean" },
68 { MONERO_PAYLOAD_TYPE_STRUCT, "struct" },
70 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_INT64, "array[int64]" },
71 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_INT32, "array[int32]" },
72 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_INT16, "array[int16]" },
73 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_INT8, "array[int8]" },
74 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_UINT64, "array[uint64]" },
75 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_UINT32, "array[uint32]" },
76 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_UINT16, "array[uint16]" },
77 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_UINT8, "array[uint8]" },
78 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_FLOAT64, "array[float64]" },
79 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_STRING, "array[string]" },
80 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_BOOLEAN, "array[boolean]" },
81 { MONERO_PAYLOAD_ARRAY | MONERO_PAYLOAD_TYPE_STRUCT, "array[struct]" },
83 { 0, NULL }
87 * Monero message header.
88 * - Network signature - 8 bytes
89 * - Body size - 8 bytes
90 * - Have to return data - 1 byte
91 * - Command - 4 bytes
92 * - Return code - 4 bytes
93 * - Flags - 4 bytes
94 * - Protocol version - 4 bytes
96 #define MONERO_HEADER_LENGTH 8+8+1+4+4+4+4
98 void proto_register_monero(void);
99 void proto_reg_handoff_monero(void);
101 static dissector_handle_t monero_handle;
103 static int proto_monero;
105 static int hf_monero_signature;
106 static int hf_monero_length;
107 static int hf_monero_havetoreturn;
108 static int hf_monero_command;
109 static int hf_monero_return_code;
110 static int hf_monero_flags;
111 static int hf_monero_flags_request;
112 static int hf_monero_flags_response;
113 static int hf_monero_flags_start_fragment;
114 static int hf_monero_flags_end_fragment;
115 static int hf_monero_flags_reserved;
116 static int hf_monero_protocol;
117 static int hf_monero_payload;
118 static int hf_monero_payload_magic;
119 static int hf_monero_payload_item;
120 static int hf_monero_payload_item_key;
121 static int hf_monero_payload_item_type;
122 static int hf_monero_payload_item_size;
123 static int hf_monero_payload_item_length;
124 static int hf_monero_payload_item_value_int8;
125 static int hf_monero_payload_item_value_int16;
126 static int hf_monero_payload_item_value_int32;
127 static int hf_monero_payload_item_value_int64;
128 static int hf_monero_payload_item_value_uint8;
129 static int hf_monero_payload_item_value_uint16;
130 static int hf_monero_payload_item_value_uint32;
131 static int hf_monero_payload_item_value_uint64;
132 static int hf_monero_payload_item_value_float64;
133 static int hf_monero_payload_item_value_string;
134 static int hf_monero_payload_item_value_boolean;
135 static int hf_monero_payload_item_value_struct;
136 static int hf_monero_payload_item_value_array;
138 static int * const flags_hf_flags[] = {
139 &hf_monero_flags_request,
140 &hf_monero_flags_response,
141 &hf_monero_flags_start_fragment,
142 &hf_monero_flags_end_fragment,
143 &hf_monero_flags_reserved,
144 NULL
147 static int ett_monero;
148 static int ett_payload;
149 static int ett_struct;
150 static int ett_flags;
152 static bool monero_desegment = true;
154 static expert_field ei_monero_type_unknown;
156 static unsigned
157 get_monero_pdu_length(packet_info *pinfo _U_, tvbuff_t *tvb,
158 int offset, void *data _U_)
160 unsigned length;
161 length = MONERO_HEADER_LENGTH;
163 /* add payload length */
164 length += (unsigned)tvb_get_letoh64(tvb, offset+8);
166 return length;
169 static void
170 get_varint(tvbuff_t *tvb, const int offset, uint8_t *length, uint64_t *ret)
172 uint8_t flag = tvb_get_uint8(tvb, offset) & 0x03;
174 switch (flag)
176 case 0:
177 *ret = tvb_get_uint8(tvb, offset) >> 2;
178 *length = 1;
179 break;
180 case 1:
181 *ret = tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN) >> 2;
182 *length = 2;
183 break;
184 case 2:
185 *ret = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN) >> 2;
186 *length = 4;
187 break;
188 case 3:
189 *ret = tvb_get_uint64(tvb, offset, ENC_LITTLE_ENDIAN) >> 2;
190 *length = 8;
191 break;
195 static int dissect_encoded_value(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, proto_item *ti, int offset, uint32_t type);
197 // we are parsing generic data structures, recursion is a first class citizen here
198 // NOLINTNEXTLINE(misc-no-recursion)
199 static int dissect_encoded_dictionary(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
201 uint8_t length;
202 uint64_t count;
203 proto_item *sti;
204 proto_tree *stree;
205 uint32_t type;
206 const uint8_t* key;
208 // number of keys in the dictionary
209 get_varint(tvb, offset, &length, &count);
210 offset += length;
212 for (; count > 0; count--)
214 sti = proto_tree_add_item(tree, hf_monero_payload_item, tvb, offset, -1, ENC_NA);
215 stree = proto_item_add_subtree(sti, ett_payload);
217 // key
218 length = tvb_get_uint8(tvb, offset);
219 offset += 1;
220 proto_tree_add_item_ret_string(stree, hf_monero_payload_item_key, tvb, offset, length, ENC_ASCII|ENC_NA, pinfo->pool, &key);
221 if(key)
222 proto_item_set_text(sti, "%s", key);
223 offset += length;
225 // type
226 proto_tree_add_item_ret_uint(stree, hf_monero_payload_item_type, tvb, offset, 1, ENC_NA, &type);
227 offset += 1;
229 // value
230 offset = dissect_encoded_value(tvb, pinfo, stree, sti, offset, type);
232 proto_item_set_end(sti, tvb, offset);
235 return offset;
238 // we are parsing generic data structures, recursion is a first class citizen here
239 // NOLINTNEXTLINE(misc-no-recursion)
240 static int dissect_encoded_value(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, proto_item *ti, int offset, uint32_t type)
242 uint8_t length;
243 uint64_t size;
244 uint64_t string_length;
245 proto_item *struct_ti;
246 proto_tree *struct_tree;
248 if (!try_val_to_str(type, payload_types)) {
249 /* The type is used to determine the length of the value; if it's unknown
250 * then we can't dissect any further. (In particular, this keeps from
251 * looping repeatedly on invalid arrays.)
253 expert_add_info(pinfo, ti, &ei_monero_type_unknown);
254 return tvb_reported_length(tvb);
257 // array of values
258 if (type & MONERO_PAYLOAD_ARRAY) {
259 get_varint(tvb, offset, &length, &size);
260 proto_tree_add_int64(tree, hf_monero_payload_item_size, tvb, offset, length, size);
261 offset += length;
263 type -= MONERO_PAYLOAD_ARRAY;
265 for (; size > 0; size--) {
266 if (type == MONERO_PAYLOAD_TYPE_STRING) {
267 struct_ti = proto_tree_add_item(tree, hf_monero_payload_item_value_array, tvb, offset, -1, ENC_NA);
268 struct_tree = proto_item_add_subtree(struct_ti, ett_struct);
270 offset = dissect_encoded_value(tvb, pinfo, struct_tree, ti, offset, type);
272 proto_item_set_end(struct_ti, tvb, offset);
274 else {
275 offset = dissect_encoded_value(tvb, pinfo, tree, ti, offset, type);
278 return offset;
281 switch (type)
283 case MONERO_PAYLOAD_TYPE_INT64:
284 proto_tree_add_item(tree, hf_monero_payload_item_value_int64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
285 offset += 8;
286 break;
288 case MONERO_PAYLOAD_TYPE_INT32:
289 proto_tree_add_item(tree, hf_monero_payload_item_value_int32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
290 offset += 4;
291 break;
293 case MONERO_PAYLOAD_TYPE_INT16:
294 proto_tree_add_item(tree, hf_monero_payload_item_value_int16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
295 offset += 2;
296 break;
298 case MONERO_PAYLOAD_TYPE_INT8:
299 proto_tree_add_item(tree, hf_monero_payload_item_value_int8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
300 offset += 1;
301 break;
303 case MONERO_PAYLOAD_TYPE_UINT64:
304 proto_tree_add_item(tree, hf_monero_payload_item_value_uint64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
305 offset += 8;
306 break;
308 case MONERO_PAYLOAD_TYPE_UINT32:
309 proto_tree_add_item(tree, hf_monero_payload_item_value_uint32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
310 offset += 4;
311 break;
313 case MONERO_PAYLOAD_TYPE_UINT16:
314 proto_tree_add_item(tree, hf_monero_payload_item_value_uint16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
315 offset += 2;
316 break;
318 case MONERO_PAYLOAD_TYPE_UINT8:
319 proto_tree_add_item(tree, hf_monero_payload_item_value_uint8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
320 offset += 1;
321 break;
323 case MONERO_PAYLOAD_TYPE_FLOAT64:
324 proto_tree_add_item(tree, hf_monero_payload_item_value_float64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
325 offset += 8;
326 break;
328 case MONERO_PAYLOAD_TYPE_STRING:
329 get_varint(tvb, offset, &length, &string_length);
330 proto_tree_add_int64(tree, hf_monero_payload_item_length, tvb, offset, length, string_length);
331 offset += length;
333 proto_tree_add_item(tree, hf_monero_payload_item_value_string, tvb, offset, (int) string_length, ENC_NA);
334 offset += (int)string_length;
335 break;
337 case MONERO_PAYLOAD_TYPE_BOOLEAN:
338 proto_tree_add_item(tree, hf_monero_payload_item_value_int64, tvb, offset, 1, ENC_LITTLE_ENDIAN);
339 offset += 1;
340 break;
342 case MONERO_PAYLOAD_TYPE_STRUCT:
343 struct_ti = proto_tree_add_item(tree, hf_monero_payload_item_value_struct, tvb, offset, -1, ENC_NA);
344 struct_tree = proto_item_add_subtree(struct_ti, ett_struct);
346 offset = dissect_encoded_dictionary(tvb, pinfo, struct_tree, offset);
347 proto_item_set_end(struct_ti, tvb, offset);
348 break;
350 default:
351 expert_add_info(pinfo, ti, &ei_monero_type_unknown);
352 offset = tvb_reported_length(tvb);
353 break;
356 return offset;
359 static void dissect_encoded_payload(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
361 proto_tree_add_item(tree, hf_monero_payload_magic, tvb, 0, 9, ENC_NA);
362 dissect_encoded_dictionary(tvb, pinfo, tree, 9);
365 static int dissect_monero_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
367 proto_item *ti, *payload_ti;
368 proto_tree *payload_tree;
369 uint32_t command;
370 const char* command_label;
371 uint64_t length;
372 uint32_t offset = 0;
374 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Monero");
376 ti = proto_tree_add_item(tree, proto_monero, tvb, 0, -1, ENC_NA);
377 tree = proto_item_add_subtree(ti, ett_monero);
379 /* header fields */
380 proto_tree_add_item(tree, hf_monero_signature, tvb, 0, 8, ENC_BIG_ENDIAN);
381 proto_tree_add_item_ret_uint64(tree, hf_monero_length, tvb, 8, 8, ENC_LITTLE_ENDIAN, &length);
382 proto_tree_add_item(tree, hf_monero_havetoreturn, tvb, 16, 1, ENC_LITTLE_ENDIAN);
383 proto_tree_add_item_ret_uint(tree, hf_monero_command, tvb, 17, 4, ENC_LITTLE_ENDIAN, &command);
384 proto_tree_add_item(tree, hf_monero_return_code, tvb, 21, 4, ENC_LITTLE_ENDIAN);
385 proto_tree_add_bitmask(tree, tvb, 25, hf_monero_flags, ett_flags, flags_hf_flags, ENC_LITTLE_ENDIAN);
386 proto_tree_add_item(tree, hf_monero_protocol, tvb, 29, 4, ENC_LITTLE_ENDIAN);
387 offset += MONERO_HEADER_LENGTH;
389 command_label = val_to_str(command, monero_commands, "[Unknown command %d]");
390 col_add_str(pinfo->cinfo, COL_INFO, command_label);
392 /* data payload */
393 payload_ti = proto_tree_add_item(tree, hf_monero_payload, tvb, offset, (int) length, ENC_NA);
394 payload_tree = proto_item_add_subtree(payload_ti, ett_payload);
395 dissect_encoded_payload(tvb_new_subset_length(tvb, offset, (int) length), pinfo, payload_tree);
396 // offset += size;
398 return tvb_reported_length(tvb);
401 static int
402 dissect_monero(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
404 col_clear(pinfo->cinfo, COL_INFO);
405 tcp_dissect_pdus(tvb, pinfo, tree, monero_desegment, MONERO_HEADER_LENGTH,
406 get_monero_pdu_length, dissect_monero_tcp_pdu, data);
408 return tvb_reported_length(tvb);
411 static bool
412 dissect_monero_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
414 uint64_t signature;
415 conversation_t *conversation;
417 if (tvb_captured_length(tvb) < 8)
418 return false;
420 signature = tvb_get_letoh64(tvb, 0);
421 if (signature != MONERO_LEVIN_SIGNATURE)
422 return false;
424 /* Ok: This connection should always use the monero dissector */
425 conversation = find_or_create_conversation(pinfo);
426 conversation_set_dissector(conversation, monero_handle);
428 dissect_monero(tvb, pinfo, tree, data);
429 return true;
432 void
433 proto_register_monero(void)
435 static hf_register_info hf[] = {
436 { &hf_monero_signature,
437 { "Signature", "monero.signature",
438 FT_UINT64, BASE_HEX, NULL, 0x0,
439 NULL, HFILL }
441 { &hf_monero_length,
442 { "Payload Length", "monero.length",
443 FT_UINT64, BASE_DEC, NULL, 0x0,
444 NULL, HFILL }
446 { &hf_monero_havetoreturn,
447 { "Have to return data", "monero.have_to_return_data",
448 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
449 NULL, HFILL }
451 { &hf_monero_command,
452 { "Command", "monero.command",
453 FT_UINT32, BASE_DEC, VALS(monero_commands), 0x0,
454 NULL, HFILL }
456 { &hf_monero_return_code,
457 { "Return Code", "monero.return_code",
458 FT_INT32, BASE_DEC, NULL, 0x0,
459 NULL, HFILL }
461 { &hf_monero_flags,
462 { "Flags", "monero.flags",
463 FT_UINT32, BASE_DEC, NULL, 0x0,
464 NULL, HFILL }
466 { &hf_monero_flags_request,
467 { "Request", "monero.flags.request",
468 FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000001,
469 NULL, HFILL }
471 { &hf_monero_flags_response,
472 { "Response", "monero.flags.response",
473 FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000002,
474 NULL, HFILL }
476 { &hf_monero_flags_start_fragment,
477 { "Start fragment", "monero.flags.start_fragment",
478 FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000004,
479 NULL, HFILL }
481 { &hf_monero_flags_end_fragment,
482 { "End fragment", "monero.flags.end_fragment",
483 FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000008,
484 NULL, HFILL }
486 { &hf_monero_flags_reserved,
487 { "Reserved", "monero.flags.reserved",
488 FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0xfffffff0,
489 NULL, HFILL }
491 { &hf_monero_protocol,
492 { "Protocol version", "monero.version",
493 FT_UINT32, BASE_DEC, NULL, 0x0,
494 NULL, HFILL }
496 { &hf_monero_payload,
497 { "Payload", "monero.payload",
498 FT_NONE, BASE_NONE, NULL, 0x0,
499 NULL, HFILL }
501 { &hf_monero_payload_magic,
502 { "Magic number", "monero.payload.magic",
503 FT_BYTES, BASE_NONE, NULL, 0x0,
504 NULL, HFILL }
506 { &hf_monero_payload_item,
507 { "Entry", "monero.payload.item",
508 FT_BYTES, BASE_NONE, NULL, 0x0,
509 NULL, HFILL }
511 { &hf_monero_payload_item_key,
512 { "Key", "monero.payload.item.key",
513 FT_STRING, BASE_NONE, NULL, 0x0,
514 NULL, HFILL }
516 { &hf_monero_payload_item_type,
517 { "Type", "monero.payload.item.type",
518 FT_UINT8, BASE_DEC, VALS(payload_types), 0x0,
519 NULL, HFILL }
521 { &hf_monero_payload_item_size,
522 { "Size", "monero.payload.item.size",
523 FT_INT64, BASE_DEC, NULL, 0x0,
524 NULL, HFILL }
526 { &hf_monero_payload_item_length,
527 { "Length", "monero.payload.item.length",
528 FT_INT64, BASE_DEC, NULL, 0x0,
529 NULL, HFILL }
531 { &hf_monero_payload_item_value_int8,
532 { "Value", "monero.payload.item.value.int8",
533 FT_INT8, BASE_DEC, NULL, 0x0,
534 NULL, HFILL }
536 { &hf_monero_payload_item_value_int16,
537 { "Value", "monero.payload.item.value.int16",
538 FT_INT16, BASE_DEC, NULL, 0x0,
539 NULL, HFILL }
541 { &hf_monero_payload_item_value_int32,
542 { "Value", "monero.payload.item.value.int32",
543 FT_INT32, BASE_DEC, NULL, 0x0,
544 NULL, HFILL }
546 { &hf_monero_payload_item_value_int64,
547 { "Value", "monero.payload.item.value.int64",
548 FT_INT64, BASE_DEC, NULL, 0x0,
549 NULL, HFILL }
551 { &hf_monero_payload_item_value_uint8,
552 { "Value", "monero.payload.item.value.uint8",
553 FT_UINT8, BASE_DEC, NULL, 0x0,
554 NULL, HFILL }
556 { &hf_monero_payload_item_value_uint16,
557 { "Value", "monero.payload.item.value.uint16",
558 FT_UINT16, BASE_DEC, NULL, 0x0,
559 NULL, HFILL }
561 { &hf_monero_payload_item_value_uint32,
562 { "Value", "monero.payload.item.value.uint32",
563 FT_UINT32, BASE_DEC, NULL, 0x0,
564 NULL, HFILL }
566 { &hf_monero_payload_item_value_uint64,
567 { "Value", "monero.payload.item.value.uint64",
568 FT_UINT64, BASE_DEC, NULL, 0x0,
569 NULL, HFILL }
571 { &hf_monero_payload_item_value_float64,
572 { "Value", "monero.payload.item.value.float64",
573 FT_DOUBLE, BASE_DEC, NULL, 0x0,
574 NULL, HFILL }
576 { &hf_monero_payload_item_value_string,
577 { "Value", "monero.payload.item.value.string",
578 FT_BYTES, BASE_NONE, NULL, 0x0,
579 NULL, HFILL }
581 { &hf_monero_payload_item_value_boolean,
582 { "Value", "monero.payload.item.value.boolean",
583 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
584 NULL, HFILL }
586 { &hf_monero_payload_item_value_struct,
587 { "Value", "monero.payload.item.value.struct",
588 FT_NONE, BASE_NONE, NULL, 0x0,
589 NULL, HFILL }
591 { &hf_monero_payload_item_value_array,
592 { "Value", "monero.payload.item.value.array",
593 FT_NONE, BASE_NONE, NULL, 0x0,
594 NULL, HFILL }
598 static int *ett[] = {
599 &ett_monero,
600 &ett_payload,
601 &ett_struct,
602 &ett_flags,
605 module_t *monero_module;
606 expert_module_t* expert_monero;
608 proto_monero = proto_register_protocol("Monero protocol", "Monero", "monero");
610 proto_register_subtree_array(ett, array_length(ett));
611 proto_register_field_array(proto_monero, hf, array_length(hf));
613 static ei_register_info ei[] = {
614 { &ei_monero_type_unknown, { "monero.payload.item.type.unknown", PI_PROTOCOL, PI_WARN, "Unknown type", EXPFILL }},
617 expert_monero = expert_register_protocol(proto_monero);
618 expert_register_field_array(expert_monero, ei, array_length(ei));
620 monero_handle = register_dissector("monero", dissect_monero, proto_monero);
622 monero_module = prefs_register_protocol(proto_monero, NULL);
623 prefs_register_bool_preference(monero_module, "desegment",
624 "Desegment all Monero messages spanning multiple TCP segments",
625 "Whether the Monero dissector should desegment all messages"
626 " spanning multiple TCP segments",
627 &monero_desegment);
631 void
632 proto_reg_handoff_monero(void)
634 dissector_add_for_decode_as_with_preference("tcp.port", monero_handle);
636 heur_dissector_add( "tcp", dissect_monero_heur, "Monero over TCP", "monero_tcp", proto_monero, HEURISTIC_ENABLE);
640 * Editor modelines - https://www.wireshark.org/tools/modelines.html
642 * Local variables:
643 * c-basic-offset: 2
644 * tab-width: 8
645 * indent-tabs-mode: nil
646 * End:
648 * vi: set shiftwidth=2 tabstop=8 expandtab:
649 * :indentSize=2:tabSize=8:noTabs=true: