Coverage Report

Created: 2026-11-12 07:01

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