Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-msgpack.c
Line
Count
Source
1
/* packet-msgpack.c
2
 *
3
 * Routines for MsgPack dissection
4
 * References:
5
 *   https://github.com/msgpack/msgpack/blob/master/spec.md
6
 *
7
 * Copyright 2018, Dario Lombardo <lomato@gmail.com>
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 */
15
16
#include "config.h"
17
18
#include <wsutil/array.h>
19
#include <epan/packet.h>
20
#include <epan/expert.h>
21
#include <epan/to_str.h>
22
23
24
25
void proto_register_msgpack(void);
26
void proto_reg_handoff_msgpack(void);
27
28
static dissector_handle_t msgpack_handle;
29
30
static int proto_msgpack;
31
32
static int hf_msgpack_string;
33
static int hf_msgpack_bin;
34
static int hf_msgpack_type;
35
static int hf_msgpack_string_len;
36
static int hf_msgpack_bin_len;
37
static int hf_msgpack_uint_fix;
38
static int hf_msgpack_uint_8;
39
static int hf_msgpack_uint_16;
40
static int hf_msgpack_uint_32;
41
static int hf_msgpack_uint_64;
42
static int hf_msgpack_int_fix;
43
static int hf_msgpack_int_8;
44
static int hf_msgpack_int_16;
45
static int hf_msgpack_int_32;
46
static int hf_msgpack_int_64;
47
static int hf_msgpack_bool;
48
static int hf_msgpack_float;
49
static int hf_msgpack_double;
50
static int hf_msgpack_ext_type;
51
static int hf_msgpack_ext_len;
52
static int hf_msgpack_ext_bytes;
53
54
static int ett_msgpack;
55
static int ett_msgpack_num;
56
static int ett_msgpack_string;
57
static int ett_msgpack_bin;
58
static int ett_msgpack_array;
59
static int ett_msgpack_map;
60
static int ett_msgpack_map_elem;
61
static int ett_msgpack_ext;
62
63
static expert_field ei_msgpack_unsupported;
64
65
/* names and ranges from https://github.com/msgpack/msgpack/blob/master/spec.md#formats */
66
static const range_string msgpack_types[] = {
67
  {0x00, 0x7F, "positive fixint"},
68
  {0x80, 0x8F, "fixmap"},
69
  {0x90, 0x9F, "fixarray"},
70
  {0xA0, 0xBF, "fixstr"},
71
  {0xC0, 0xC0, "nil"},
72
  {0xC1, 0xC1, "(never used)"},
73
  {0xC2, 0xC2, "false"},
74
  {0xC3, 0xC3, "true"},
75
  {0xC4, 0xC4, "bin 8"},
76
  {0xC5, 0xC5, "bin 16"},
77
  {0xC6, 0xC6, "bin 32"},
78
  {0xC7, 0xC7, "ext 8"},
79
  {0xC8, 0xC8, "ext 16"},
80
  {0xC9, 0xC9, "ext 32"},
81
  {0xCA, 0xCA, "float 32"},
82
  {0xCB, 0xCB, "flost 64"},
83
  {0xCC, 0xCC, "uint 8"},
84
  {0xCD, 0xCD, "uint 16"},
85
  {0xCE, 0xCE, "uint 32"},
86
  {0xCF, 0xCF, "uint 64"},
87
  {0xD0, 0xD0, "int 8"},
88
  {0xD1, 0xD1, "int 16"},
89
  {0xD2, 0xD2, "int 32"},
90
  {0xD3, 0xD3, "int 64"},
91
  {0xD4, 0xD4, "fixext 1"},
92
  {0xD5, 0xD5, "fixext 2"},
93
  {0xD6, 0xD6, "fixext 4"},
94
  {0xD7, 0xD7, "fixext 8"},
95
  {0xD8, 0xD8, "fixext 16"},
96
  {0xD9, 0xD9, "str 8"},
97
  {0xDA, 0xDA, "str 16"},
98
  {0xDB, 0xDB, "str 32"},
99
  {0xDC, 0xDC, "array 16"},
100
  {0xDD, 0xDD, "array 32"},
101
  {0xDE, 0xDE, "map 16"},
102
  {0xDF, 0xDF, "map 32"},
103
  {0xE0, 0xFF, "negative fixint"},
104
  {0x00, 0x00, NULL}
105
};
106
107
static void dissect_msgpack_object(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data, unsigned* offset, char** value);
108
109
static void dissect_msgpack_integer(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree, uint8_t type, void* data, unsigned* offset, char** value)
110
0
{
111
0
  uint8_t uint8;
112
0
  uint16_t uint16;
113
0
  uint32_t uint32;
114
0
  uint64_t uint64;
115
0
  int8_t int8;
116
0
  int16_t int16;
117
0
  int32_t int32;
118
0
  int64_t int64;
119
0
  char* label;
120
0
  proto_tree* subtree;
121
0
  proto_item* ti;
122
0
  int t_offset = *offset;
123
124
0
  label = (data ? (char*)data : "MsgPack Integer");
125
126
0
  if (type >> 7 == 0) {
127
0
    ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_fix, tvb, *offset, 1, type, "%s: %u", label, type);
128
0
    subtree = proto_item_add_subtree(ti, ett_msgpack_num);
129
0
    proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA);
130
131
0
    if (value)
132
0
      *value = wmem_strdup_printf(pinfo->pool, "%u", type);
133
0
    *offset += 1;
134
0
    return;
135
0
  }
136
137
0
  if (type >> 5 == 7) {
138
0
    int8_t stype = (int8_t)type;
139
0
    ti = proto_tree_add_int_format(tree, hf_msgpack_int_fix, tvb, *offset, 1, stype, "%s: %d", label, stype);
140
0
    subtree = proto_item_add_subtree(ti, ett_msgpack_num);
141
0
    proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA);
142
143
0
    if (value)
144
0
      *value = wmem_strdup_printf(pinfo->pool, "%d", stype);
145
0
    *offset += 1;
146
0
    return;
147
0
  }
148
149
0
  switch (type) {
150
0
    case 0xcc:
151
0
      uint8 = tvb_get_uint8(tvb, *offset + 1);
152
0
      ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_8, tvb, *offset, 2, uint8, "%s: %u", label, uint8);
153
0
      if (value)
154
0
        *value = wmem_strdup_printf(pinfo->pool, "%u", uint8);
155
0
      *offset += 2;
156
0
      break;
157
0
    case 0xcd:
158
0
      uint16 = tvb_get_ntohs(tvb, *offset + 1);
159
0
      ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_16, tvb, *offset, 3, uint16, "%s: %u", label, uint16);
160
0
      if (value)
161
0
        *value = wmem_strdup_printf(pinfo->pool, "%u", uint16);
162
0
      *offset += 3;
163
0
      break;
164
0
    case 0xce:
165
0
      uint32 = tvb_get_ntohl(tvb, *offset + 1);
166
0
      ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_32, tvb, *offset, 5, uint32, "%s: %u", label, uint32);
167
0
      if (value)
168
0
        *value = wmem_strdup_printf(pinfo->pool, "%u", uint32);
169
0
      *offset += 5;
170
0
      break;
171
0
    case 0xcf:
172
0
      uint64 = tvb_get_ntoh64(tvb, *offset + 1);
173
0
      ti = proto_tree_add_uint64_format(tree, hf_msgpack_uint_64, tvb, *offset, 9, uint64, "%s: %" PRIu64, label, uint64);
174
0
      if (value)
175
0
        *value = wmem_strdup_printf(pinfo->pool, "%" PRIu64, uint64);
176
0
      *offset += 9;
177
0
      break;
178
0
    case 0xd0:
179
0
      int8 = tvb_get_int8(tvb, *offset + 1);
180
0
      ti = proto_tree_add_int_format(tree, hf_msgpack_int_8, tvb, *offset, 2, int8, "%s: %d", label, int8);
181
0
      if (value)
182
0
        *value = wmem_strdup_printf(pinfo->pool, "%d", int8);
183
0
      *offset += 2;
184
0
      break;
185
0
    case 0xd1:
186
0
      int16 = tvb_get_ntohs(tvb, *offset + 1);
187
0
      ti = proto_tree_add_int_format(tree, hf_msgpack_int_16, tvb, *offset, 3, int16, "%s: %d", label, int16);
188
0
      if (value)
189
0
        *value = wmem_strdup_printf(pinfo->pool, "%d", int16);
190
0
      *offset += 3;
191
0
      break;
192
0
    case 0xd2:
193
0
      int32 = tvb_get_ntohl(tvb, *offset + 1);
194
0
      ti = proto_tree_add_int_format(tree, hf_msgpack_int_32, tvb, *offset, 5, int32, "%s: %d", label, int32);
195
0
      if (value)
196
0
        *value = wmem_strdup_printf(pinfo->pool, "%d", int32);
197
0
      *offset += 5;
198
0
      break;
199
0
    case 0xd3:
200
0
      int64 = tvb_get_ntoh64(tvb, *offset + 1);
201
0
      ti = proto_tree_add_int64_format(tree, hf_msgpack_int_64, tvb, *offset, 9, int64, "%s: %" PRId64, label, int64);
202
0
      if (value)
203
0
        *value = wmem_strdup_printf(pinfo->pool, "%" PRId64, int64);
204
0
      *offset += 9;
205
0
      break;
206
0
    default:
207
0
      DISSECTOR_ASSERT_NOT_REACHED();
208
0
      break;
209
0
  }
210
0
  subtree = proto_item_add_subtree(ti, ett_msgpack_num);
211
0
  proto_tree_add_item(subtree, hf_msgpack_type, tvb, t_offset, 1, ENC_NA);
212
0
}
213
214
// NOLINTNEXTLINE(misc-no-recursion)
215
static void dissect_msgpack_map(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, uint8_t type, void* data, unsigned* offset, char** value)
216
0
{
217
0
  proto_tree* subtree;
218
0
  proto_tree* map_subtree;
219
0
  proto_item* ti;
220
0
  uint32_t len = 0;
221
0
  uint8_t lensize = 0;
222
0
  char* label;
223
0
  unsigned i;
224
225
0
  if (type >> 4 == 0x8) {
226
0
    len = type & 0x0F;
227
0
    lensize = 0;
228
0
  }
229
0
  else if (type == 0xde) {
230
0
    len = tvb_get_ntohs(tvb, *offset + 1);
231
0
    lensize = 2;
232
0
  }
233
0
  else if (type == 0xdf) {
234
0
    len = tvb_get_ntohl(tvb, *offset + 1);
235
0
    lensize = 4;
236
0
  }
237
0
  else {
238
0
    DISSECTOR_ASSERT_NOT_REACHED();
239
0
  }
240
241
0
  label = wmem_strdup_printf(pinfo->pool, "%s: %u element%s", data ? (char*)data : "MsgPack Map", len, len > 1 ? "s" : "");
242
243
0
  ti = proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1 + lensize, NULL, "%s", label);
244
0
  subtree = proto_item_add_subtree(ti, ett_msgpack_map);
245
0
  proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA);
246
0
  *offset += lensize + 1;
247
0
  for (i = 0; i < len; i++) {
248
    // We recurse here, but we'll run out of packet before we run out of stack.
249
0
    map_subtree = proto_tree_add_subtree(subtree, tvb, *offset, 0, ett_msgpack_map_elem, NULL, "");
250
0
    dissect_msgpack_object(tvb, pinfo, map_subtree, "Key", offset, value);
251
0
    if (value)
252
0
      proto_item_append_text(map_subtree, " %s:", *value);
253
0
    dissect_msgpack_object(tvb, pinfo, map_subtree, "Value", offset, value);
254
0
    if (value)
255
0
      proto_item_append_text(map_subtree, " %s", *value);
256
0
  }
257
258
0
  if (value)
259
0
    *value = label;
260
0
}
261
262
// NOLINTNEXTLINE(misc-no-recursion)
263
static void dissect_msgpack_array(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, uint8_t type, void* data, unsigned* offset, char** value)
264
0
{
265
0
  proto_tree* subtree;
266
0
  proto_item* ti;
267
0
  uint32_t len = 0;
268
0
  uint8_t lensize = 0;
269
0
  char* label;
270
0
  unsigned i;
271
272
0
  if (type >> 4 == 0x9) {
273
0
    len = type & 0x0F;
274
0
    lensize = 0;
275
0
  }
276
0
  else if (type == 0xdc) {
277
0
    len = tvb_get_ntohs(tvb, *offset + 1);
278
0
    lensize = 2;
279
0
  }
280
0
  else if (type == 0xdd) {
281
0
    len = tvb_get_ntohl(tvb, *offset + 1);
282
0
    lensize = 4;
283
0
  }
284
0
  else {
285
0
    DISSECTOR_ASSERT_NOT_REACHED();
286
0
  }
287
288
0
  label = wmem_strdup_printf(pinfo->pool, "%s %u element%s", data ? (char*)data : "MsgPack Array", len, len > 1 ? "s" : "");
289
290
0
  ti = proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1 + lensize, NULL, "%s", label);
291
0
  subtree = proto_item_add_subtree(ti, ett_msgpack_array);
292
0
  proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA);
293
0
  *offset += lensize + 1;
294
0
  for (i = 0; i < len; i++) {
295
    // We recurse here, but we'll run out of packet before we run out of stack.
296
0
    dissect_msgpack_object(tvb, pinfo, subtree, data, offset, value);
297
0
  }
298
299
0
  if (value)
300
0
    *value = label;
301
0
}
302
303
static void dissect_msgpack_string(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int type, void* data, unsigned* offset, char** value)
304
0
{
305
0
  uint32_t len = 0;
306
0
  uint8_t lensize = 0;
307
0
  char* label;
308
0
  proto_item* ti;
309
0
  proto_tree* subtree;
310
0
  char* lvalue;
311
312
0
  if (type >> 5 == 0x5) {
313
0
    len = type & 0x1F;
314
0
    lensize = 0;
315
0
  }
316
0
  else if (type == 0xd9) {
317
0
    len = tvb_get_uint8(tvb, *offset + 1);
318
0
    lensize = 1;
319
0
  }
320
0
  else if (type == 0xda) {
321
0
    len = tvb_get_ntohs(tvb, *offset + 1);
322
0
    lensize = 2;
323
0
  }
324
0
  else if (type == 0xdb) {
325
0
    len = tvb_get_ntohl(tvb, *offset + 1);
326
0
    lensize = 4;
327
0
  }
328
0
  else {
329
0
    DISSECTOR_ASSERT_NOT_REACHED();
330
0
  }
331
332
0
  lvalue = (char*)tvb_get_string_enc(pinfo->pool, tvb, *offset + 1 + lensize, len, ENC_UTF_8);
333
0
  label = (data ? (char*)data : "MsgPack String");
334
335
0
  ti = proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1 + lensize + len, lvalue, "%s: %s", label, lvalue);
336
0
  subtree = proto_item_add_subtree(ti, ett_msgpack_string);
337
0
  proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA);
338
339
0
  if (lensize == 0) {
340
0
    proto_tree_add_uint(subtree, hf_msgpack_string_len, tvb, *offset, 1, len);
341
0
    *offset += 1;
342
0
  }
343
0
  else {
344
0
    *offset += 1;
345
0
    proto_tree_add_item(subtree, hf_msgpack_string_len, tvb, *offset, lensize, ENC_BIG_ENDIAN);
346
0
    *offset += lensize;
347
0
  }
348
0
  proto_tree_add_item(subtree, hf_msgpack_string, tvb, *offset, len, ENC_UTF_8);
349
0
  *offset += len;
350
351
0
  if (value)
352
0
    *value = lvalue;
353
0
}
354
355
static void dissect_msgpack_bin(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int type, void* data, unsigned* offset, char** value)
356
0
{
357
0
  uint32_t len = 0;
358
0
  uint8_t lensize = 0;
359
0
  char* label;
360
0
  proto_item* ti;
361
0
  proto_tree* subtree;
362
0
  char* lvalue;
363
364
0
  switch (type) {
365
0
    case 0xc4:
366
0
      len = tvb_get_uint8(tvb, *offset + 1);
367
0
      lensize = 1;
368
0
      break;
369
0
    case 0xc5:
370
0
      len = tvb_get_ntohs(tvb, *offset + 1);
371
0
      lensize = 2;
372
0
      break;
373
0
    case 0xc6:
374
0
      len = tvb_get_ntohl(tvb, *offset + 1);
375
0
      lensize = 4;
376
0
      break;
377
0
    default:
378
0
      DISSECTOR_ASSERT_NOT_REACHED();
379
0
      break;
380
0
  }
381
382
0
  lvalue = (char*)tvb_bytes_to_str(pinfo->pool, tvb, *offset + 1 + lensize, len);
383
0
  label = (data ? (char*)data : "MsgPack Bytes");
384
385
0
  ti = proto_tree_add_bytes_format(tree, hf_msgpack_bin, tvb, *offset, 1 + lensize + len, NULL, "%s: %s", label, lvalue);
386
0
  subtree = proto_item_add_subtree(ti, ett_msgpack_bin);
387
0
  proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA);
388
389
0
  *offset += 1;
390
0
  proto_tree_add_item(subtree, hf_msgpack_bin_len, tvb, *offset, lensize, ENC_BIG_ENDIAN);
391
0
  *offset += lensize;
392
393
0
  proto_tree_add_item(subtree, hf_msgpack_bin, tvb, *offset, len, ENC_NA);
394
0
  *offset += len;
395
396
0
  if (value)
397
0
    *value = lvalue;
398
0
}
399
400
static void dissect_msgpack_float(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree, int type, void* data, unsigned* offset, char** value)
401
0
{
402
0
  char* label;
403
0
  char* lvalue;
404
0
  proto_item* ti;
405
0
  proto_tree* subtree;
406
0
  int s_offset = *offset;
407
408
0
  *offset += 1;
409
410
0
  if (type == 0xca) {
411
0
    label = (data ? (char*)data : "MsgPack Float");
412
0
    float f = tvb_get_ntohieee_float(tvb, *offset);
413
0
    lvalue = wmem_strdup_printf(pinfo->pool, "%f", f);
414
0
    ti = proto_tree_add_float_format(tree, hf_msgpack_float, tvb, *offset, 4, f, "%s: %f", label, f);
415
0
    if (value)
416
0
      *value = lvalue;
417
0
    *offset += 4;
418
0
  }
419
0
  else if (type == 0xcb) {
420
0
    label = (data ? (char*)data : "MsgPack Double");
421
0
    double d = tvb_get_ntohieee_double(tvb, *offset);
422
0
    lvalue = wmem_strdup_printf(pinfo->pool, "%lf", d);
423
0
    ti = proto_tree_add_double_format(tree, hf_msgpack_double, tvb, *offset, 8, d, "%s: %lf", label, d);
424
0
    if (value)
425
0
      *value = lvalue;
426
0
    *offset += 8;
427
0
  }
428
0
  else {
429
0
    DISSECTOR_ASSERT_NOT_REACHED();
430
0
  }
431
0
  subtree = proto_item_add_subtree(ti, ett_msgpack_num);
432
0
  proto_tree_add_item(subtree, hf_msgpack_type, tvb, s_offset, 1, ENC_NA);
433
0
}
434
435
static void dissect_msgpack_ext(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree, int type, void* data, unsigned* offset, char** value)
436
0
{
437
0
  char* label;
438
0
  uint32_t len = 0;
439
0
  uint8_t lensize = 0;
440
0
  proto_tree* subtree;
441
0
  unsigned offset_start = *offset;
442
443
0
  label = (data ? (char*)data : "Ext");
444
445
0
  subtree = proto_tree_add_subtree(tree, tvb, *offset, 0, ett_msgpack_ext, NULL, label);
446
447
0
  proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA);
448
0
  if (type >= 0xd4 && type <= 0xd8) {
449
0
    len = 1 << (type - 0xd4);
450
0
    proto_tree_add_uint(subtree, hf_msgpack_ext_len, tvb, *offset, 1, len);
451
0
  }
452
0
  else if (type == 0xc7) {
453
0
    len = tvb_get_uint8(tvb, *offset + 2);
454
0
    lensize = 1;
455
0
  }
456
0
  else if (type == 0xc8) {
457
0
    len = tvb_get_ntohs(tvb, *offset + 2);
458
0
    lensize = 2;
459
0
  }
460
0
  else if (type == 0xc9) {
461
0
    len = tvb_get_ntohl(tvb, *offset + 2);
462
0
    lensize = 4;
463
0
  }
464
0
  else {
465
0
    DISSECTOR_ASSERT_NOT_REACHED();
466
0
  }
467
0
  *offset += 1;
468
469
0
  proto_tree_add_item(subtree, hf_msgpack_ext_type, tvb, *offset, 1, ENC_NA);
470
0
  *offset += 1;
471
472
0
  if (lensize > 0) {
473
0
    proto_tree_add_item(subtree, hf_msgpack_ext_len, tvb, *offset, lensize, ENC_BIG_ENDIAN);
474
0
    *offset += lensize;
475
0
  }
476
0
  proto_tree_add_item(subtree, hf_msgpack_ext_bytes, tvb, *offset, len, ENC_NA);
477
0
  if (value) {
478
0
    *value = tvb_bytes_to_str(pinfo->pool, tvb, *offset, len);
479
0
  }
480
0
  *offset += len;
481
482
0
  proto_item_set_len(subtree, *offset - offset_start);
483
0
}
484
485
// NOLINTNEXTLINE(misc-no-recursion)
486
static void dissect_msgpack_object(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data, unsigned* offset, char** value)
487
0
{
488
0
  uint8_t type;
489
0
  int s_offset = *offset;
490
491
0
  type = tvb_get_uint8(tvb, *offset);
492
493
0
  col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", rval_to_str_const(type, msgpack_types, " Unknown Msg Type"));
494
495
  // Nil
496
0
  if (type == 0xc0) {
497
0
    proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1, "nil", "nil");
498
0
    if (value)
499
0
      *value = "nil";
500
0
    *offset += 1;
501
0
    return;
502
0
  }
503
504
  // True/False
505
0
  if (type == 0xc2 || type == 0xc3) {
506
0
    proto_tree_add_boolean(tree, hf_msgpack_bool, tvb, *offset, 1, type - 0xc2);
507
0
    if (value)
508
0
      *value = (type - 0xc2) ? "True" : "False";
509
0
    *offset += 1;
510
0
    return;
511
0
  }
512
513
  // Integer
514
0
  if (type >= 0xe0 || type <= 0x7f || (type >= 0xcc && type <= 0xd3)) {
515
0
    dissect_msgpack_integer(tvb, pinfo, tree, type, data, offset, value);
516
0
    return;
517
0
  }
518
519
  // Float
520
0
  if (type == 0xca || type == 0xcb) {
521
0
    dissect_msgpack_float(tvb, pinfo, tree, type, data, offset, value);
522
0
    return;
523
0
  }
524
525
  // String
526
0
  if (type >> 5 == 0x5 || type == 0xd9 || type == 0xda || type == 0xdb) {
527
0
    dissect_msgpack_string(tvb, pinfo, tree, type, data, offset, value);
528
0
    return;
529
0
  }
530
531
  // Bin
532
0
  if (type == 0xc4 || type == 0xc5 || type == 0xc6) {
533
0
    dissect_msgpack_bin(tvb, pinfo, tree, type, data, offset, value);
534
0
    return;
535
0
  }
536
537
  // Array
538
0
  if (type >> 4 == 0x9 || type == 0xdc || type == 0xdd) {
539
    // We recurse here, but we'll run out of packet before we run out of stack.
540
0
    dissect_msgpack_array(tvb, pinfo, tree, type, data, offset, value);
541
0
    return;
542
0
  }
543
544
  // Map
545
0
  if (type >> 4 == 0x8 || type == 0xde || type == 0xdf) {
546
    // We recurse here, but we'll run out of packet before we run out of stack.
547
0
    dissect_msgpack_map(tvb, pinfo, tree, type, data, offset, value);
548
0
    return;
549
0
  }
550
551
  // Ext
552
0
  if ((type >= 0xd4 && type <= 0xd8) || (type >= 0xc7 && type <= 0xc9)) {
553
0
    dissect_msgpack_ext(tvb, pinfo, tree, type, data, offset, value);
554
0
    return;
555
0
  }
556
557
0
  if (*offset - s_offset == 0) {
558
0
    expert_add_info_format(pinfo, tree, &ei_msgpack_unsupported, "Type 0x%x is unsupported", type);
559
0
  }
560
0
}
561
562
static int dissect_msgpack(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data)
563
0
{
564
0
  unsigned offset = 0;
565
566
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "MsgPack");
567
0
  col_clear(pinfo->cinfo, COL_INFO);
568
569
0
  dissect_msgpack_object(tvb, pinfo, tree, data, &offset, NULL);
570
0
  return offset;
571
0
}
572
573
void proto_register_msgpack(void)
574
14
{
575
14
  expert_module_t* expert_msgpack;
576
577
14
  static hf_register_info hf[] = {
578
14
    { &hf_msgpack_string,
579
14
      { "String", "msgpack.string", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }
580
14
    },
581
14
    { &hf_msgpack_type,
582
14
      { "Type", "msgpack.type", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(msgpack_types), 0x00, NULL, HFILL }
583
14
    },
584
14
    { &hf_msgpack_string_len,
585
14
      { "Length", "msgpack.string.len", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
586
14
    },
587
14
    { &hf_msgpack_bin,
588
14
      { "Bytes", "msgpack.bin", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }
589
14
    },
590
14
    { &hf_msgpack_bin_len,
591
14
      { "Length", "msgpack.bin.len", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
592
14
    },
593
14
    { &hf_msgpack_uint_fix,
594
14
      { "Integer", "msgpack.integer.fixint", FT_UINT8, BASE_DEC, NULL, 0x7F, NULL, HFILL }
595
14
    },
596
14
    { &hf_msgpack_uint_8,
597
14
      { "Integer", "msgpack.integer.u8", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }
598
14
    },
599
14
    { &hf_msgpack_uint_16,
600
14
      { "Integer", "msgpack.integer.u16", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }
601
14
    },
602
14
    { &hf_msgpack_uint_32,
603
14
      { "Integer", "msgpack.integer.u32", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
604
14
    },
605
14
    { &hf_msgpack_uint_64,
606
14
      { "Integer", "msgpack.integer.u64", FT_UINT64, BASE_DEC, NULL, 0x00, NULL, HFILL }
607
14
    },
608
14
    { &hf_msgpack_int_fix,
609
14
      { "Integer", "msgpack.integer.fixint", FT_INT8, BASE_DEC, NULL, 0x1F, NULL, HFILL }
610
14
    },
611
14
    { &hf_msgpack_int_8,
612
14
      { "Integer", "msgpack.integer.8", FT_INT8, BASE_DEC, NULL, 0x00, NULL, HFILL }
613
14
    },
614
14
    { &hf_msgpack_int_16,
615
14
      { "Integer", "msgpack.integer.16", FT_INT16, BASE_DEC, NULL, 0x00, NULL, HFILL }
616
14
    },
617
14
    { &hf_msgpack_int_32,
618
14
      { "Integer", "msgpack.integer.32", FT_INT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
619
14
    },
620
14
    { &hf_msgpack_int_64,
621
14
      { "Integer", "msgpack.integer.64", FT_INT64, BASE_DEC, NULL, 0x00, NULL, HFILL }
622
14
    },
623
14
    { &hf_msgpack_bool,
624
14
      { "Boolean", "msgpack.boolean", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
625
14
    },
626
14
    { &hf_msgpack_float,
627
14
      { "Float", "msgpack.float", FT_FLOAT, BASE_NONE, NULL, 0x00, NULL, HFILL }
628
14
    },
629
14
    { &hf_msgpack_double,
630
14
      { "Double", "msgpack.double", FT_DOUBLE, BASE_NONE, NULL, 0x00, NULL, HFILL }
631
14
    },
632
14
    { &hf_msgpack_ext_type,
633
14
      { "Ext type", "msgpack.ext.type", FT_INT8, BASE_DEC, NULL, 0x00, NULL, HFILL }
634
14
    },
635
14
    { &hf_msgpack_ext_len,
636
14
      { "Length", "msgpack.ext.len", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
637
14
    },
638
14
    { &hf_msgpack_ext_bytes,
639
14
      { "Ext", "msgpack.ext", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }
640
14
    }
641
14
  };
642
643
14
  static int* ett[] = {
644
14
    &ett_msgpack,
645
14
    &ett_msgpack_num,
646
14
    &ett_msgpack_string,
647
14
    &ett_msgpack_bin,
648
14
    &ett_msgpack_array,
649
14
    &ett_msgpack_map,
650
14
    &ett_msgpack_map_elem,
651
14
    &ett_msgpack_ext
652
14
  };
653
654
14
  static ei_register_info ei[] = {
655
14
    { &ei_msgpack_unsupported, { "msgpack.unsupported", PI_UNDECODED, PI_WARN, "Unsupported type", EXPFILL }}
656
14
  };
657
658
14
  proto_msgpack = proto_register_protocol("Message Pack", "MsgPack", "msgpack");
659
14
  msgpack_handle = register_dissector("msgpack", dissect_msgpack, proto_msgpack);
660
661
14
  expert_msgpack = expert_register_protocol(proto_msgpack);
662
14
  expert_register_field_array(expert_msgpack, ei, array_length(ei));
663
664
14
  proto_register_field_array(proto_msgpack, hf, array_length(hf));
665
14
  proto_register_subtree_array(ett, array_length(ett));
666
14
}
667
668
void proto_reg_handoff_msgpack(void)
669
14
{
670
  // If this is ever streamed (transported over TCP) we need to add recursion checks
671
14
  dissector_add_for_decode_as("udp.port", msgpack_handle);
672
14
}
673
674
/*
675
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
676
 *
677
 * Local variables:
678
 * c-basic-offset: 8
679
 * tab-width: 8
680
 * indent-tabs-mode: t
681
 * End:
682
 *
683
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
684
 * :indentSize=8:tabSize=8:noTabs=false:
685
 */