Coverage Report

Created: 2026-09-28 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
 */