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-cbor.c
Line
Count
Source
1
/* packet-cbor.c
2
 * Routines for Concise Binary Object Representation (CBOR) (STD 94) dissection
3
 * References:
4
 *     RFC 8949: https://tools.ietf.org/html/rfc8949
5
 *     RFC 8742: https://tools.ietf.org/html/rfc8742
6
 *     RFC 8610: https://tools.ietf.org/html/rfc8610
7
 *
8
 * Copyright 2015, Hauke Mehrtens <hauke@hauke-m.de>
9
 * Copyright 2022, Stig Bjorlykke <stig@bjorlykke.org>
10
 *
11
 * Wireshark - Network traffic analyzer
12
 * By Gerald Combs <gerald@wireshark.org>
13
 * Copyright 1998 Gerald Combs
14
 *
15
 * SPDX-License-Identifier: GPL-2.0-or-later
16
 */
17
18
#include "config.h"
19
20
#include <math.h>
21
22
#include "packet-cbor.h"
23
#include <epan/packet.h>
24
#include <epan/exceptions.h>
25
#include <epan/expert.h>
26
#include <epan/proto_data.h>
27
#include <epan/wscbor.h>
28
#include <wsutil/str_util.h>
29
#include <wsutil/to_str.h>
30
31
void proto_register_cbor(void);
32
void proto_reg_handoff_cbor(void);
33
34
enum {
35
  /// No diagnostic text
36
  CBOR_DIAG_NONE,
37
  /// One diagnostic at the top of the tree
38
  CBOR_DIAG_TOP,
39
  /// One diagnostic for each CBOR item, including the top
40
  CBOR_DIAG_ALL,
41
};
42
static const enum_val_t cbor_display_diagnostic_choices[] = {
43
  {"none", "Disabled", CBOR_DIAG_NONE},
44
  {"top", "Only for the top item", CBOR_DIAG_TOP},
45
  {"all", "For all items recursively", CBOR_DIAG_ALL},
46
  {NULL, NULL, 0},
47
};
48
49
// Protocol preferences and defaults
50
static bool cbor_dissect_embeded_bstr = false;
51
static int cbor_display_diagnostic = CBOR_DIAG_NONE;
52
static bool cbor_diagnostic_bstr_text = true;
53
54
static int proto_cbor;
55
56
static int hf_cbor_item_major_type;
57
static int hf_cbor_item_integer_size;
58
static int hf_cbor_item_length_size;
59
static int hf_cbor_item_length5;
60
static int hf_cbor_item_length;
61
static int hf_cbor_item_items5;
62
static int hf_cbor_item_items;
63
static int hf_cbor_item_pairs5;
64
static int hf_cbor_item_pairs;
65
static int hf_cbor_item_float_simple_type;
66
static int hf_cbor_item_unsigned_integer;
67
static int hf_cbor_item_negative_integer;
68
static int hf_cbor_item_text_string;
69
static int hf_cbor_item_byte_string;
70
static int hf_cbor_item_array;
71
static int hf_cbor_item_map;
72
static int hf_cbor_item_tag;
73
static int hf_cbor_item_float_simple;
74
static int hf_cbor_type_uint5;
75
static int hf_cbor_type_uint;
76
static int hf_cbor_type_nint;
77
static int hf_cbor_type_byte_string;
78
static int hf_cbor_type_byte_string_indef;
79
static int hf_cbor_type_text_string;
80
static int hf_cbor_type_text_string_indef;
81
static int hf_cbor_type_tag;
82
static int hf_cbor_type_simple_data5;
83
static int hf_cbor_type_simple_data8;
84
static int hf_cbor_type_float16;
85
static int hf_cbor_type_float32;
86
static int hf_cbor_type_float64;
87
static int hf_cbor_seq_len;
88
static int hf_cbor_diag_text;
89
90
static int ett_cbor;
91
static int ett_cbor_type;
92
static int ett_cbor_unsigned_integer;
93
static int ett_cbor_negative_integer;
94
static int ett_cbor_byte_string;
95
static int ett_cbor_byte_string_indef;
96
static int ett_cbor_text_string;
97
static int ett_cbor_text_string_indef;
98
static int ett_cbor_array;
99
static int ett_cbor_map;
100
static int ett_cbor_tag;
101
static int ett_cbor_float_simple;
102
103
static expert_field ei_cbor_invalid_minor_type;
104
static expert_field ei_cbor_invalid_element;
105
static expert_field ei_cbor_too_long_length;
106
static expert_field ei_cbor_max_recursion_depth_reached;
107
static expert_field ei_cbor_embedded_bstr;
108
109
static dissector_handle_t cbor_handle;
110
static dissector_handle_t cborseq_handle;
111
112
static heur_dissector_list_t cbor_bstr_heur;
113
114
21.9k
#define CBOR_TYPE_USIGNED_INT   0
115
6.10k
#define CBOR_TYPE_NEGATIVE_INT  1
116
1.84k
#define CBOR_TYPE_BYTE_STRING   2
117
2.20k
#define CBOR_TYPE_TEXT_STRING   3
118
5.22k
#define CBOR_TYPE_ARRAY   4
119
6.02k
#define CBOR_TYPE_MAP   5
120
4.83k
#define CBOR_TYPE_TAGGED  6
121
10.2k
#define CBOR_TYPE_FLOAT   7
122
123
static const value_string major_type_vals[] = {
124
  { 0, "Unsigned Integer" },
125
  { 1, "Negative Integer" },
126
  { 2, "Byte String" },
127
  { 3, "Text String" },
128
  { 4, "Array" },
129
  { 5, "Map" },
130
  { 6, "Tagged" },
131
  { 7, "Floating-Point or Simple" },
132
  { 0, NULL }
133
};
134
135
static const value_string integer_size_vals[] = {
136
  { 24, "1 byte" },
137
  { 25, "2 bytes" },
138
  { 26, "4 bytes" },
139
  { 27, "8 bytes" },
140
  { 28, "Reserved for future additions" },
141
  { 29, "Reserved for future additions" },
142
  { 30, "Reserved for future additions" },
143
  { 31, "No argument value is derived" },
144
  { 0, NULL }
145
};
146
147
static const value_string length_size_vals[] = {
148
  { 24, "1 byte" },
149
  { 25, "2 bytes" },
150
  { 26, "4 bytes" },
151
  { 27, "8 bytes" },
152
  { 28, "Reserved for future additions" },
153
  { 29, "Reserved for future additions" },
154
  { 30, "Reserved for future additions" },
155
  { 31, "Indefinite Length" },
156
  { 0, NULL }
157
};
158
159
static const value_string float_simple_type_vals[] = {
160
  { 24, "Simple value" },
161
  { 25, "IEEE 754 Half-Precision Float" },
162
  { 26, "IEEE 754 Single-Precision Float" },
163
  { 27, "IEEE 754 Double-Precision Float" },
164
  { 28, "Reserved for future additions" },
165
  { 29, "Reserved for future additions" },
166
  { 30, "Reserved for future additions" },
167
  { 31, "Break indefinite length" },
168
  { 0, NULL }
169
};
170
171
/* see https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml#tags */
172
static const val64_string tag64_vals[] = {
173
  { 0, "Standard date/time string" },
174
  { 1, "Epoch-based date/time" },
175
  { 2, "Positive bignum" },
176
  { 3, "Negative bignum" },
177
  { 4, "Decimal fraction" },
178
  { 5, "Bigfloat" },
179
  { 16, "COSE Single Recipient Encrypted Data Object" },
180
  { 17, "COSE Mac w/o Recipients Object" },
181
  { 18, "COSE Single Signer Data Object" },
182
  { 19, "COSE standalone V2 countersignature" },
183
  { 21, "Expected conversion to base64url encoding" },
184
  { 22, "Expected conversion to base64 encoding" },
185
  { 23, "Expected conversion to base16 encoding" },
186
  { 24, "Encoded CBOR data item" },
187
  { 25, "reference the nth previously seen string" },
188
  { 26, "Serialised Perl object with classname and constructor arguments" },
189
  { 27, "Serialised language-independent object with type name and constructor arguments" },
190
  { 28, "mark value as (potentially) shared" },
191
  { 29, "reference nth marked value" },
192
  { 30, "Rational number" },
193
  { 32, "URI" },
194
  { 33, "base64url" },
195
  { 34, "base64" },
196
  { 35, "Regular expression" },
197
  { 36, "MIME message" },
198
  { 37, "Binary UUID" },
199
  { 38, "Language-tagged string" },
200
  { 39, "Identifier" },
201
  { 61, "CBOR Web Token (CWT)" },
202
  { 63, "Encoded CBOR Sequence" },
203
  { 100, "Number of days since the epoch date 1970-01-01" },
204
  { 256, "mark value as having string references" },
205
  { 257, "Binary MIME message" },
206
  { 264, "Decimal fraction with arbitrary exponent" },
207
  { 265, "Bigfloat with arbitrary exponent" },
208
  { 1004, "RFC 3339 full-date string" },
209
  { 22098, "hint that indicates an additional level of indirection" },
210
  { 55799, "Self-describe CBOR" },
211
  { 0, NULL },
212
};
213
/// Display text for simple values
214
static const value_string vals_simple_data[] = {
215
  { 20, "False" },
216
  { 21, "True" },
217
  { 22, "Null" },
218
  { 23, "Undefined" },
219
  { 0, NULL },
220
};
221
/// Diagnostic form of simple values
222
static const value_string vals_simple_diag[] = {
223
  { 20, "false" },
224
  { 21, "true" },
225
  { 22, "null" },
226
  { 23, "undefined" },
227
  { 0, NULL },
228
};
229
230
/// Context for CBOR diagnostic notation text
231
typedef struct {
232
  /// Working buffer to append to
233
  wmem_strbuf_t *buf;
234
  /// Stack of parent item buffers
235
  wmem_stack_t *stack;
236
} cbor_diag_ctx_t;
237
238
/** Initialize a diagnostic text context.
239
 *
240
 * @param[out] ptr The pointer to replace if NULL.
241
 * @param[in] alloc The packet allocator to use.
242
 * @param is_sequence True if decoding a sequence with diagnostic above the top items.
243
 */
244
9.03k
static void cbor_diag_ctx_init(cbor_diag_ctx_t **ptr, wmem_allocator_t *alloc, bool is_sequence) {
245
9.03k
  if (!*ptr && (cbor_display_diagnostic != CBOR_DIAG_NONE)) {
246
0
    *ptr = wmem_new0(alloc, cbor_diag_ctx_t);
247
0
    (*ptr)->buf = is_sequence ? wmem_strbuf_new(alloc, NULL) : NULL;
248
0
    (*ptr)->stack = wmem_stack_new(alloc);
249
0
  }
250
9.03k
}
251
252
/** Extract the current value from a diagnostic context.
253
 *
254
 * @param[in] ctx The context to read from or NULL if not valid.
255
 * @param type_major Used for specific cases of indefinite length strings.
256
 * @return The diagnostic text, which may be augmented from the direct buffer.
257
 */
258
0
static const char * cbor_diag_ctx_get(const cbor_diag_ctx_t *ctx, uint8_t type_major) {
259
0
  if (!ctx) {
260
0
    return "/invalid/";
261
0
  }
262
0
  const char *got = wmem_strbuf_get_str(ctx->buf);
263
0
  if (strcmp(got, "(_ )") == 0) {
264
0
    got = (type_major == CBOR_TYPE_BYTE_STRING) ? "''_" : "\"\"_";
265
0
  }
266
0
  return got;
267
0
}
268
269
static bool
270
dissect_cbor_main_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, cbor_diag_ctx_t *ctx);
271
272
static bool
273
dissect_cbor_float_simple_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx);
274
275
static bool
276
dissect_cbor_unsigned_integer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx)
277
21.9k
{
278
21.9k
  uint64_t value = 0;
279
21.9k
  proto_item *item;
280
21.9k
  proto_tree *subtree;
281
282
21.9k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_unsigned_integer, tvb, *offset, -1, ENC_NA);
283
21.9k
  subtree = proto_item_add_subtree(item, ett_cbor_unsigned_integer);
284
285
21.9k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
286
21.9k
  if (type_minor <= 0x17) {
287
21.3k
    proto_tree_add_item(subtree, hf_cbor_type_uint5, tvb, *offset, 1, ENC_BIG_ENDIAN);
288
21.3k
    value = type_minor;
289
21.3k
  } else {
290
629
    proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
291
629
  }
292
21.9k
  *offset += 1;
293
294
21.9k
  switch (type_minor) {
295
243
  case 0x18:
296
243
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 1, ENC_BIG_ENDIAN, &value);
297
243
    *offset += 1;
298
243
    break;
299
255
  case 0x19:
300
255
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 2, ENC_BIG_ENDIAN, &value);
301
255
    *offset += 2;
302
255
    break;
303
62
  case 0x1a:
304
62
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 4, ENC_BIG_ENDIAN, &value);
305
62
    *offset += 4;
306
62
    break;
307
52
  case 0x1b:
308
52
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 8, ENC_BIG_ENDIAN, &value);
309
52
    *offset += 8;
310
52
    break;
311
21.3k
  default:
312
21.3k
    if (type_minor > 0x17) {
313
17
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
314
17
          "invalid minor type %i in unsigned integer", type_minor);
315
17
      return false;
316
17
    }
317
21.3k
    break;
318
21.9k
  }
319
320
21.9k
  proto_item_append_text(item, ": %" PRIu64, value);
321
21.9k
  proto_item_set_end(item, tvb, *offset);
322
323
21.9k
  if (ctx) {
324
0
    wmem_strbuf_append_printf(ctx->buf, "%" PRIu64, value);
325
0
  }
326
327
21.9k
  return true;
328
21.9k
}
329
330
static bool
331
dissect_cbor_negative_integer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx)
332
6.10k
{
333
6.10k
  uint64_t arg = 0;
334
6.10k
  int64_t value = 0;
335
6.10k
  proto_item *item;
336
6.10k
  proto_tree *subtree;
337
338
6.10k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_negative_integer, tvb, *offset, -1, ENC_NA);
339
6.10k
  subtree = proto_item_add_subtree(item, ett_cbor_negative_integer);
340
341
6.10k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
342
6.10k
  if (type_minor <= 0x17) {
343
5.17k
    arg = type_minor;
344
5.17k
    value = (int64_t)-1 - arg;
345
    /* Keep correct bit representation with a modified value. */
346
5.17k
    proto_tree_add_int64_bits_format_value(subtree, hf_cbor_type_nint, tvb, 3, 5, type_minor, ENC_BIG_ENDIAN, "%" PRId64, value);
347
5.17k
  } else {
348
928
    proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
349
928
  }
350
6.10k
  *offset += 1;
351
352
6.10k
  switch (type_minor) {
353
236
  case 0x18:
354
236
    arg = tvb_get_uint8(tvb, *offset);
355
236
    value = (int64_t)-1 - arg;
356
236
    proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 1, value);
357
236
    *offset += 1;
358
236
    break;
359
259
  case 0x19:
360
259
    arg = tvb_get_ntohs(tvb, *offset);
361
259
    value = (int64_t)-1 - arg;
362
259
    proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 2, value);
363
259
    *offset += 2;
364
259
    break;
365
193
  case 0x1a:
366
193
    arg = tvb_get_ntohl(tvb, *offset);
367
193
    value = (int64_t)-1 - arg;
368
193
    proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 4, value);
369
193
    *offset += 4;
370
193
    break;
371
210
  case 0x1b:
372
210
    arg = tvb_get_ntoh64(tvb, *offset);
373
    /* TODO: an overflow could happen here, for negative int < INT64_MIN */
374
210
    value = (int64_t)-1 - arg;
375
210
    if (value > -1) {
376
88
      expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length,
377
88
        "The value is too negative, Wireshark can not display it correctly");
378
88
    }
379
210
    proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 8, value);
380
210
    *offset += 8;
381
210
    break;
382
5.20k
  default:
383
5.20k
    if (type_minor > 0x17) {
384
30
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
385
30
          "invalid minor type %i in negative integer", type_minor);
386
30
      return false;
387
30
    }
388
5.17k
    break;
389
6.10k
  }
390
391
6.06k
  if (arg == UINT64_MAX) {
392
1
    proto_item_append_text(item, ": -18446744073709551616");
393
1
  }
394
6.06k
  else {
395
6.06k
    proto_item_append_text(item, ": -%" PRIu64, arg + 1);
396
6.06k
  }
397
6.06k
  proto_item_set_end(item, tvb, *offset);
398
399
6.06k
  if (ctx) {
400
0
    if (arg == UINT64_MAX) {
401
0
      wmem_strbuf_append(ctx->buf, "-18446744073709551616");
402
0
    }
403
0
    else {
404
0
      wmem_strbuf_append_printf(ctx->buf, "-%" PRIu64, arg + 1);
405
0
    }
406
0
  }
407
408
6.06k
  return true;
409
6.10k
}
410
411
/** Escape the quote character itself after escaping non-printable text.
412
 */
413
static char *
414
0
cbor_diag_escape(wmem_allocator_t *alloc, const char *in, char quote) {
415
0
  const char reject[2] = { quote };
416
417
0
  wmem_strbuf_t *buf = wmem_strbuf_new(alloc, NULL);
418
0
  while (*in) {
419
0
    size_t width = strcspn(in, reject);
420
0
    if (width) {
421
0
      wmem_strbuf_append_len(buf, in, width);
422
0
      in += width;
423
0
    }
424
0
    if (*in) {
425
0
      wmem_strbuf_append_printf(buf, "\\%c", quote);
426
0
      ++in;
427
0
    }
428
0
  }
429
0
  return wmem_strbuf_finalize(buf);
430
0
}
431
432
static bool
433
// NOLINTNEXTLINE(misc-no-recursion)
434
dissect_cbor_byte_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx)
435
1.82k
{
436
1.82k
  uint64_t length;
437
1.82k
  int      eof_type;
438
1.82k
  proto_tree *subtree;
439
1.82k
  proto_item *item;
440
441
1.82k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_byte_string, tvb, *offset, -1, ENC_NA);
442
1.82k
  subtree = proto_item_add_subtree(item, ett_cbor_byte_string);
443
444
1.82k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
445
1.82k
  if (type_minor <= 0x17) {
446
1.36k
    proto_tree_add_item(subtree, hf_cbor_item_length5, tvb, *offset, 1, ENC_BIG_ENDIAN);
447
1.36k
    length = type_minor;
448
1.36k
  } else {
449
467
    proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
450
467
  }
451
1.82k
  *offset += 1;
452
453
1.82k
  switch (type_minor) {
454
71
  case 0x18:
455
71
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 1, ENC_BIG_ENDIAN, &length);
456
71
    *offset += 1;
457
71
    break;
458
7
  case 0x19:
459
7
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 2, ENC_BIG_ENDIAN, &length);
460
7
    *offset += 2;
461
7
    break;
462
7
  case 0x1a:
463
7
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 4, ENC_BIG_ENDIAN, &length);
464
7
    *offset += 4;
465
7
    break;
466
29
  case 0x1b:
467
29
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 8, ENC_BIG_ENDIAN, &length);
468
29
    *offset += 8;
469
29
    break;
470
345
  case 0x1f: {
471
345
    proto_item_append_text(item, ": (indefinite length)");
472
345
    item = proto_tree_add_item(subtree, hf_cbor_type_byte_string_indef, tvb, *offset, 1, ENC_NA);
473
345
    subtree = proto_item_add_subtree(item, ett_cbor_byte_string_indef);
474
345
    if (ctx) {
475
0
      wmem_strbuf_append_printf(ctx->buf, "(_ ");
476
0
    }
477
345
    bool first = true;
478
382
    while (1) {
479
382
      eof_type = tvb_get_uint8(tvb, *offset);
480
382
      if (eof_type == 0xff) {
481
66
        dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f, ctx);
482
66
        proto_item_set_end(item, tvb, *offset);
483
66
        if (ctx) {
484
0
          wmem_strbuf_append_printf(ctx->buf, ")");
485
0
        }
486
66
        return true;
487
66
      }
488
489
316
      if (((eof_type & 0xe0) >> 5) != CBOR_TYPE_BYTE_STRING) {
490
16
        expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_element,
491
16
          "invalid element %i, expected byte string", (eof_type & 0xe0) >> 5);
492
16
        return false;
493
16
      }
494
495
300
      unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor);
496
300
      if (recursion_depth > prefs.gui_max_tree_depth) {
497
0
        proto_tree_add_expert(subtree, pinfo, &ei_cbor_max_recursion_depth_reached, tvb, 0, 0);
498
0
        return false;
499
0
      }
500
300
      p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1);
501
502
300
      if (ctx) {
503
0
        if (first) {
504
0
          first = false;
505
0
        }
506
0
        else {
507
0
          wmem_strbuf_append(ctx->buf, ", ");
508
0
        }
509
0
      }
510
300
      bool recursed = dissect_cbor_byte_string(tvb, pinfo, subtree, offset, eof_type & 0x1f, ctx);
511
300
      p_set_proto_depth(pinfo, proto_cbor, recursion_depth);
512
513
300
      if (!recursed) {
514
263
        return false;
515
263
      }
516
300
    }
517
0
    DISSECTOR_ASSERT_NOT_REACHED();
518
0
    return false;
519
345
  }
520
1.37k
  default:
521
1.37k
    if (type_minor > 0x17) {
522
8
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
523
8
          "invalid minor type %i in byte string", type_minor);
524
8
      return false;
525
8
    }
526
1.36k
    break;
527
1.82k
  }
528
529
1.47k
  if (length > INT32_MAX) {
530
20
    expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length,
531
20
      "the length (%" PRIu64 ") of the byte string too long", length);
532
20
    return false;
533
20
  }
534
535
1.45k
  proto_item *item_data = proto_tree_add_item(subtree, hf_cbor_type_byte_string, tvb, *offset, (int)length, ENC_NA);
536
1.45k
  if (ckd_add(offset, *offset, length)) {
537
0
    expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length,
538
0
      "the length (%" PRIu64 ") of the byte string too long", length);
539
0
    return false;
540
0
  }
541
542
1.45k
  proto_item_append_text(item, ": (%" PRIu64 " byte%s)", length, plurality(length, "", "s"));
543
1.45k
  proto_item_set_end(item, tvb, *offset);
544
1.45k
  unsigned int_start = *offset - (unsigned)length;
545
546
1.45k
  tvbuff_t *content_tvb = tvb_new_subset_length(tvb, int_start, (unsigned)length);
547
548
1.45k
  bool heur_valid = false;
549
1.45k
  if (cbor_dissect_embeded_bstr && length) {
550
0
    heur_dtbl_entry_t *entry = NULL;
551
0
    heur_valid = dissector_try_heuristic(cbor_bstr_heur, content_tvb, pinfo, subtree, &entry, ctx);
552
0
    if (heur_valid) {
553
0
      expert_add_info_format(pinfo, item_data, &ei_cbor_embedded_bstr, "Heuristic dissection matched as: %s", entry->display_name);
554
0
    }
555
0
  }
556
557
1.45k
  if (ctx && !heur_valid) {
558
0
    if (cbor_diagnostic_bstr_text && tvb_utf_8_isprint_remaining(content_tvb, 0)) {
559
0
      char *text = tvb_format_text(pinfo->pool, content_tvb, 0, (unsigned)length);
560
0
      wmem_strbuf_append_printf(ctx->buf, "'%s'", cbor_diag_escape(pinfo->pool, text, '\''));
561
0
    }
562
0
    else {
563
0
      char *hexstr = bytes_to_str_maxlen(pinfo->pool, tvb_get_ptr(content_tvb, 0, (unsigned)length), length, length);
564
0
      wmem_strbuf_append_printf(ctx->buf, "h'%s'", hexstr);
565
0
    }
566
0
  }
567
568
1.45k
  return true;
569
1.45k
}
570
571
static bool
572
// NOLINTNEXTLINE(misc-no-recursion)
573
dissect_cbor_text_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx)
574
2.18k
{
575
2.18k
  const uint8_t *value = NULL;
576
2.18k
  uint64_t length = 0;
577
2.18k
  int      eof_type, new_offset;
578
2.18k
  proto_tree *subtree;
579
2.18k
  proto_item *item;
580
581
2.18k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_text_string, tvb, *offset, -1, ENC_NA);
582
2.18k
  subtree = proto_item_add_subtree(item, ett_cbor_text_string);
583
584
2.18k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
585
2.18k
  if (type_minor <= 0x17) {
586
1.79k
    proto_tree_add_item(subtree, hf_cbor_item_length5, tvb, *offset, 1, ENC_BIG_ENDIAN);
587
1.79k
    length = type_minor;
588
1.79k
  } else {
589
385
    proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
590
385
  }
591
2.18k
  *offset += 1;
592
593
2.18k
  switch (type_minor) {
594
27
  case 0x18:
595
27
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 1, ENC_BIG_ENDIAN, &length);
596
27
    *offset += 1;
597
27
    break;
598
14
  case 0x19:
599
14
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 2, ENC_BIG_ENDIAN, &length);
600
14
    *offset += 2;
601
14
    break;
602
17
  case 0x1a:
603
17
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 4, ENC_BIG_ENDIAN, &length);
604
17
    *offset += 4;
605
17
    break;
606
4
  case 0x1b:
607
4
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 8, ENC_BIG_ENDIAN, &length);
608
4
    *offset += 8;
609
4
    break;
610
306
  case 0x1f: {
611
306
    proto_item_append_text(item, ": (indefinite length)");
612
306
    item = proto_tree_add_item(subtree, hf_cbor_type_text_string_indef, tvb, *offset, 1, ENC_NA);
613
306
    subtree = proto_item_add_subtree(item, ett_cbor_text_string_indef);
614
306
    if (ctx) {
615
0
      wmem_strbuf_append_printf(ctx->buf, "(_ ");
616
0
    }
617
306
    bool first = true;
618
437
    while (1) {
619
389
      eof_type = tvb_get_uint8(tvb, *offset);
620
389
      if (eof_type == 0xff) {
621
119
        dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f, ctx);
622
119
        proto_item_set_end(item, tvb, *offset);
623
119
        if (ctx) {
624
0
          wmem_strbuf_append_printf(ctx->buf, ")");
625
0
        }
626
119
        return true;
627
119
      }
628
629
270
      if (((eof_type & 0xe0) >> 5) != CBOR_TYPE_TEXT_STRING) {
630
15
        expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_element,
631
15
          "invalid element %i, expected text string", (eof_type & 0xe0) >> 5);
632
15
        return false;
633
15
      }
634
635
255
      unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor);
636
255
      if (recursion_depth > prefs.gui_max_tree_depth) {
637
0
        proto_tree_add_expert(subtree, pinfo, &ei_cbor_max_recursion_depth_reached, tvb, 0, 0);
638
0
        return false;
639
0
      }
640
255
      p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1);
641
642
255
      if (ctx) {
643
0
        if (first) {
644
0
          first = false;
645
0
        }
646
0
        else {
647
0
          wmem_strbuf_append(ctx->buf, ", ");
648
0
        }
649
0
      }
650
255
      bool recursed = dissect_cbor_text_string(tvb, pinfo, subtree, offset, eof_type & 0x1f, ctx);
651
255
      p_set_proto_depth(pinfo, proto_cbor, recursion_depth);
652
653
255
      if (!recursed) {
654
124
        return false;
655
124
      }
656
255
    }
657
48
    DISSECTOR_ASSERT_NOT_REACHED();
658
48
    return false;
659
306
  }
660
1.81k
  default:
661
1.81k
    if (type_minor > 0x17) {
662
17
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
663
17
          "invalid minor type %i in text string", type_minor);
664
17
      return false;
665
17
    }
666
1.79k
    break;
667
2.18k
  }
668
669
1.85k
  if (ckd_add(&new_offset, *offset, length)) {
670
9
    expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length,
671
9
      "the length (%" PRIu64 ") of the text string too long", length);
672
9
    return false;
673
9
  }
674
675
1.84k
  tvbuff_t *content_tvb = tvb_new_subset_length(tvb, *offset, (unsigned)length);
676
1.84k
  proto_tree_add_item_ret_string(subtree, hf_cbor_type_text_string, content_tvb, 0, (int)length, ENC_BIG_ENDIAN|ENC_UTF_8, pinfo->pool, &value);
677
1.84k
  *offset = new_offset;
678
679
1.84k
  proto_item_append_text(item, ": %s", value);
680
1.84k
  proto_item_set_end(item, tvb, *offset);
681
682
1.84k
  if (ctx) {
683
0
    char *text = tvb_format_text(pinfo->pool, content_tvb, 0, (unsigned)length);
684
0
    wmem_strbuf_append_printf(ctx->buf, "\"%s\"", cbor_diag_escape(pinfo->pool, text, '"'));
685
0
  }
686
687
1.84k
  return true;
688
1.85k
}
689
690
static bool
691
// NOLINTNEXTLINE(misc-no-recursion)
692
dissect_cbor_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx)
693
5.22k
{
694
5.22k
  uint64_t length = 0;
695
5.22k
  proto_tree *subtree;
696
5.22k
  proto_item *item;
697
5.22k
  bool        indefinite = false;
698
699
5.22k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_array, tvb, *offset, -1, ENC_NA);
700
5.22k
  subtree = proto_item_add_subtree(item, ett_cbor_array);
701
702
5.22k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
703
704
5.22k
  if (type_minor <= 0x17) {
705
3.88k
    proto_tree_add_item(subtree, hf_cbor_item_items5, tvb, *offset, 1, ENC_BIG_ENDIAN);
706
3.88k
    length = type_minor;
707
3.88k
  } else {
708
1.33k
    proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
709
1.33k
  }
710
5.22k
  *offset += 1;
711
712
5.22k
  switch (type_minor) {
713
445
  case 0x18:
714
445
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 1, ENC_BIG_ENDIAN, &length);
715
445
    *offset += 1;
716
445
    break;
717
70
  case 0x19:
718
70
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 2, ENC_BIG_ENDIAN, &length);
719
70
    *offset += 2;
720
70
    break;
721
93
  case 0x1a:
722
93
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 4, ENC_BIG_ENDIAN, &length);
723
93
    *offset += 4;
724
93
    break;
725
117
  case 0x1b:
726
117
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 8, ENC_BIG_ENDIAN, &length);
727
117
    *offset += 8;
728
117
    break;
729
608
  case 0x1f:
730
608
    length = INT_MAX;
731
608
    indefinite = true;
732
608
    break;
733
3.89k
  default:
734
3.89k
    if (type_minor > 0x17) {
735
5
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
736
5
          "invalid minor type %i in array", type_minor);
737
5
      return false;
738
5
    }
739
3.88k
    break;
740
5.22k
  }
741
742
5.22k
  if (ctx) {
743
0
    wmem_strbuf_append(ctx->buf, indefinite ? "[_ " : "[");
744
0
  }
745
746
21.3k
  for (uint64_t i = 0; i < length; i++) {
747
17.9k
    if (indefinite) {
748
1.52k
      int value = tvb_get_uint8(tvb, *offset);
749
1.52k
      if (value == 0xff) {
750
152
        dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f, ctx);
751
152
        break;
752
152
      }
753
1.52k
    }
754
755
17.7k
    if (ctx && (i != 0)) {
756
0
      wmem_strbuf_append(ctx->buf, ", ");
757
0
    }
758
759
17.7k
    if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset, ctx)) {
760
1.67k
      return false;
761
1.67k
    }
762
17.7k
  }
763
764
3.54k
  if (ctx) {
765
0
    wmem_strbuf_append(ctx->buf, "]");
766
0
  }
767
768
3.54k
  if (indefinite) {
769
152
    proto_item_append_text(item, ": (indefinite length)");
770
3.39k
  } else {
771
3.39k
    proto_item_append_text(item, ": (%" PRIu64 " item%s)", length, plurality(length, "", "s"));
772
3.39k
  }
773
3.54k
  proto_item_set_end(item, tvb, *offset);
774
775
3.54k
  return true;
776
5.22k
}
777
778
static bool
779
// NOLINTNEXTLINE(misc-no-recursion)
780
dissect_cbor_map(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx)
781
6.02k
{
782
6.02k
  uint64_t    length = 0;
783
6.02k
  proto_tree *subtree;
784
6.02k
  proto_item *item;
785
6.02k
  bool        indefinite = false;
786
787
6.02k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_map, tvb, *offset, -1, ENC_NA);
788
6.02k
  subtree = proto_item_add_subtree(item, ett_cbor_map);
789
790
6.02k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
791
792
6.02k
  if (type_minor <= 0x17) {
793
4.66k
    proto_tree_add_item(subtree, hf_cbor_item_pairs5, tvb, *offset, 1, ENC_BIG_ENDIAN);
794
4.66k
    length = type_minor;
795
4.66k
  } else {
796
1.35k
    proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
797
1.35k
  }
798
6.02k
  *offset += 1;
799
800
6.02k
  switch (type_minor) {
801
380
  case 0x18:
802
380
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 1, ENC_BIG_ENDIAN, &length);
803
380
    *offset += 1;
804
380
    break;
805
176
  case 0x19:
806
176
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 2, ENC_BIG_ENDIAN, &length);
807
176
    *offset += 2;
808
176
    break;
809
224
  case 0x1a:
810
224
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 4, ENC_BIG_ENDIAN, &length);
811
224
    *offset += 4;
812
224
    break;
813
236
  case 0x1b:
814
236
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 8, ENC_BIG_ENDIAN, &length);
815
236
    *offset += 8;
816
236
    break;
817
335
  case 0x1f:
818
335
    length = INT_MAX;
819
335
    indefinite = true;
820
335
    break;
821
4.67k
  default:
822
4.67k
    if (type_minor > 0x17) {
823
4
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
824
4
          "invalid minor type %i in map", type_minor);
825
4
      return false;
826
4
    }
827
4.66k
    break;
828
6.02k
  }
829
830
6.01k
  if (ctx) {
831
0
    wmem_strbuf_append(ctx->buf, indefinite ? "{_ " : "{");
832
0
  }
833
834
15.0k
  for (uint64_t i = 0; i < length; i++) {
835
11.7k
    if (indefinite) {
836
1.38k
      int value = tvb_get_uint8(tvb, *offset);
837
1.38k
      if (value == 0xff) {
838
93
        dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f, ctx);
839
93
        break;
840
93
      }
841
1.38k
    }
842
843
11.6k
    if (ctx && (i != 0)) {
844
0
      wmem_strbuf_append(ctx->buf, ", ");
845
0
    }
846
847
11.6k
    if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset, ctx)) {
848
2.41k
      return false;
849
2.41k
    }
850
851
9.23k
    if (ctx) {
852
0
      wmem_strbuf_append(ctx->buf, ": ");
853
0
    }
854
855
9.23k
    if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset, ctx)) {
856
243
      return false;
857
243
    }
858
9.23k
  }
859
860
3.35k
  if (ctx) {
861
0
    wmem_strbuf_append(ctx->buf, "}");
862
0
  }
863
864
3.35k
  if (indefinite) {
865
93
    proto_item_append_text(item, ": (indefinite length)");
866
3.25k
  } else {
867
3.25k
    proto_item_append_text(item, ": (%" PRIu64 " pair%s)", length, plurality(length, "", "s"));
868
3.25k
  }
869
3.35k
  proto_item_set_end(item, tvb, *offset);
870
871
3.35k
  return true;
872
6.01k
}
873
874
static bool
875
// NOLINTNEXTLINE(misc-no-recursion)
876
dissect_cbor_tag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx)
877
4.83k
{
878
4.83k
  uint64_t         tag = 0;
879
4.83k
  proto_item      *item;
880
4.83k
  proto_tree      *subtree;
881
882
4.83k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_tag, tvb, *offset, -1, ENC_NA);
883
4.83k
  subtree = proto_item_add_subtree(item, ett_cbor_tag);
884
885
4.83k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
886
887
4.83k
  if (type_minor <= 0x17) {
888
4.13k
    tag = type_minor;
889
4.13k
    proto_tree_add_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 1, tag);
890
4.13k
  } else {
891
701
    proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN);
892
701
  }
893
4.83k
  *offset += 1;
894
895
4.83k
  switch (type_minor) {
896
187
  case 0x18:
897
187
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 1, ENC_BIG_ENDIAN, &tag);
898
187
    *offset += 1;
899
187
    break;
900
230
  case 0x19:
901
230
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 2, ENC_BIG_ENDIAN, &tag);
902
230
    *offset += 2;
903
230
    break;
904
131
  case 0x1a:
905
131
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 4, ENC_BIG_ENDIAN, &tag);
906
131
    *offset += 4;
907
131
    break;
908
138
  case 0x1b:
909
138
    proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 8, ENC_BIG_ENDIAN, &tag);
910
138
    *offset += 8;
911
138
    break;
912
4.15k
  default:
913
4.15k
    if (type_minor > 0x17) {
914
15
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
915
15
          "invalid minor type %i in tag", type_minor);
916
15
      return false;
917
15
    }
918
4.13k
    break;
919
4.83k
  }
920
921
4.82k
  if (ctx) {
922
0
    wmem_strbuf_append_printf(ctx->buf, "%" PRIu64 "(", tag);
923
0
  }
924
925
4.82k
  if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset, ctx)) {
926
401
    return false;
927
401
  }
928
929
4.42k
  if (ctx) {
930
0
    wmem_strbuf_append(ctx->buf, ")");
931
0
  }
932
933
4.42k
  proto_item_append_text(item, ": %s (%" PRIu64 ")", val64_to_str_wmem(pinfo->pool, tag, tag64_vals, "Unknown"), tag);
934
4.42k
  proto_item_set_end(item, tvb, *offset);
935
936
4.42k
  return true;
937
4.82k
}
938
939
/* based on code from rfc7049 appendix-D */
940
static float
941
decode_half(tvbuff_t *tvb, proto_tree *tree, proto_item *item, int *offset, int hfindex)
942
314
{
943
314
  int half, exponent, mantissa;
944
314
  float val = 0;
945
946
314
  half = tvb_get_ntohs(tvb, *offset);
947
314
  exponent = (half >> 10) & 0x1f;
948
314
  mantissa = half & 0x3ff;
949
950
314
  if (exponent == 0) {
951
51
    val = ldexpf((float)mantissa, -24);
952
51
    if (half & 0x8000) {
953
21
      val = -val;
954
21
    }
955
51
    proto_tree_add_float(tree, hfindex, tvb, *offset, 2, val);
956
51
    proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", val);
957
263
  } else if (exponent != 31) {
958
233
    val = ldexpf((float)(mantissa + 1024), exponent - 25);
959
233
    if (half & 0x8000) {
960
202
      val = -val;
961
202
    }
962
233
    proto_tree_add_float(tree, hfindex, tvb, *offset, 2, val);
963
233
    proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", val);
964
233
  } else {
965
30
    val = (mantissa == 0) ? INFINITY : NAN;
966
30
    if (half & 0x8000) {
967
22
      val = -val;
968
22
    }
969
30
    proto_tree_add_float_format_value(tree, hfindex, tvb, *offset, 2, 0, "%f", val);
970
30
    proto_item_set_text(item, "Float: %f", val);
971
30
  }
972
314
  return val;
973
314
}
974
975
#define CBOR_DIAG_FLOAT(buf, fmt, val)               \
976
0
  if (isnan(val)) {                                \
977
0
    wmem_strbuf_append(buf, "NaN");              \
978
0
  }                                                \
979
0
  else if (isinf(val)) {                           \
980
0
    if (val < 0) {                               \
981
0
      wmem_strbuf_append(buf, "-");            \
982
0
    }                                            \
983
0
    wmem_strbuf_append(buf, "Infinity");         \
984
0
  }                                                \
985
0
  else {                                           \
986
0
    char tmp[G_ASCII_DTOSTR_BUF_SIZE];           \
987
0
    g_ascii_formatd(tmp, sizeof(tmp), fmt, val); \
988
0
    wmem_strbuf_append(buf, tmp);                \
989
0
  }
990
991
992
static bool
993
dissect_cbor_float_simple_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx)
994
10.7k
{
995
10.7k
  uint32_t         simple;
996
10.7k
  float            f_value;
997
10.7k
  double           d_value;
998
10.7k
  proto_item      *item;
999
10.7k
  proto_tree      *subtree;
1000
1001
10.7k
  item = proto_tree_add_item(cbor_tree, hf_cbor_item_float_simple, tvb, *offset, -1, ENC_NA);
1002
10.7k
  subtree = proto_item_add_subtree(item, ett_cbor_float_simple);
1003
1004
10.7k
  proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
1005
1006
10.7k
  if (type_minor <= 0x17) {
1007
2.88k
    proto_tree_add_item_ret_uint(subtree, hf_cbor_type_simple_data5, tvb, *offset, 1, ENC_BIG_ENDIAN, &simple);
1008
2.88k
    proto_item_set_text(item, "Simple: %s (%u)", val_to_str_const(simple, vals_simple_data, "Unknown"), simple);
1009
2.88k
    if (ctx) {
1010
0
      wmem_strbuf_append_printf(ctx->buf, "%s", val_to_str(pinfo->pool, simple, vals_simple_diag, "simple(%u)"));
1011
0
    }
1012
7.84k
  } else {
1013
7.84k
    proto_tree_add_item(subtree, hf_cbor_item_float_simple_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
1014
7.84k
  }
1015
10.7k
  *offset += 1;
1016
1017
10.7k
  switch (type_minor) {
1018
199
  case 0x18:
1019
199
    proto_tree_add_item_ret_uint(subtree, hf_cbor_type_simple_data8, tvb, *offset, 1, ENC_BIG_ENDIAN, &simple);
1020
199
    proto_item_set_text(item, "Simple: %s (%u)", val_to_str_const(simple, vals_simple_data, "Unknown"), simple);
1021
199
    *offset += 1;
1022
199
    if (ctx) {
1023
0
      wmem_strbuf_append_printf(ctx->buf, "%s", val_to_str(pinfo->pool, simple, vals_simple_diag, "simple(%u)"));
1024
0
    }
1025
199
    break;
1026
314
  case 0x19:
1027
314
    f_value = decode_half(tvb, subtree, item, offset, hf_cbor_type_float16);
1028
314
    *offset += 2;
1029
314
    if (ctx) {
1030
0
      CBOR_DIAG_FLOAT(ctx->buf, "%#." G_STRINGIFY(FLT_DIG) "g", f_value);
1031
0
    }
1032
314
    break;
1033
138
  case 0x1a:
1034
138
    f_value = tvb_get_ntohieee_float(tvb, *offset);
1035
138
    proto_tree_add_item(subtree, hf_cbor_type_float32, tvb, *offset, 4, ENC_BIG_ENDIAN);
1036
138
    proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", f_value);
1037
138
    *offset += 4;
1038
138
    if (ctx) {
1039
0
      CBOR_DIAG_FLOAT(ctx->buf, "%#." G_STRINGIFY(DBL_DIG) "g", f_value);
1040
0
    }
1041
138
    break;
1042
107
  case 0x1b:
1043
107
    d_value = tvb_get_ntohieee_double(tvb, *offset);
1044
107
    proto_tree_add_item(subtree, hf_cbor_type_float64, tvb, *offset, 8, ENC_BIG_ENDIAN);
1045
107
    proto_item_set_text(item, "Float: %." G_STRINGIFY(DBL_DIG) "g", d_value);
1046
107
    *offset += 8;
1047
107
    if (ctx) {
1048
0
      CBOR_DIAG_FLOAT(ctx->buf, "%#." G_STRINGIFY(DBL_DIG) "g", d_value);
1049
0
    }
1050
107
    break;
1051
7.06k
  case 0x1f:
1052
7.06k
    proto_item_set_text(item, "Break indefinite length (%u)", type_minor);
1053
7.06k
    break;
1054
2.90k
  default:
1055
2.90k
    if (type_minor > 0x17) {
1056
25
      expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type,
1057
25
          "invalid minor type %i in simple data and float", type_minor);
1058
25
      return false;
1059
25
    }
1060
2.88k
    break;
1061
10.7k
  }
1062
1063
10.6k
  proto_item_set_end(item, tvb, *offset);
1064
1065
10.6k
  return true;
1066
10.7k
}
1067
1068
1069
static bool
1070
// NOLINTNEXTLINE(misc-no-recursion)
1071
dissect_cbor_main_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, cbor_diag_ctx_t *ctx)
1072
57.9k
{
1073
57.9k
  uint8_t     type;
1074
57.9k
  uint8_t     type_major;
1075
57.9k
  uint8_t     type_minor;
1076
57.9k
  int         init_offset = *offset;
1077
1078
57.9k
  type = tvb_get_uint8(tvb, *offset);
1079
1080
57.9k
  type_major = (type & 0xe0) >> 5;
1081
57.9k
  type_minor = (type & 0x1f);
1082
1083
57.9k
  unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor);
1084
  /* dissect_cbor_main_type and dissect_cbor_tag/dissect_cbor_map can exhaust
1085
   * the stack calling each other recursively on malformed packets otherwise */
1086
57.9k
  if (recursion_depth > prefs.gui_max_tree_depth) {
1087
0
    proto_tree_add_expert(cbor_tree, pinfo, &ei_cbor_max_recursion_depth_reached, tvb, 0, 0);
1088
0
    return false;
1089
0
  }
1090
57.9k
  p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1);
1091
1092
57.9k
  if (ctx) {
1093
0
    wmem_stack_push(ctx->stack, ctx->buf);
1094
0
    ctx->buf = wmem_strbuf_new(pinfo->pool, NULL);
1095
0
  }
1096
1097
57.9k
  bool valid = false;
1098
57.9k
  switch (type_major) {
1099
21.9k
  case CBOR_TYPE_USIGNED_INT:
1100
21.9k
    valid = dissect_cbor_unsigned_integer(tvb, pinfo, cbor_tree, offset, type_minor, ctx);
1101
21.9k
    break;
1102
6.10k
  case CBOR_TYPE_NEGATIVE_INT:
1103
6.10k
    valid = dissect_cbor_negative_integer(tvb, pinfo, cbor_tree, offset, type_minor, ctx);
1104
6.10k
    break;
1105
1.52k
  case CBOR_TYPE_BYTE_STRING:
1106
1.52k
    valid = dissect_cbor_byte_string(tvb, pinfo, cbor_tree, offset, type_minor, ctx);
1107
1.52k
    break;
1108
1.93k
  case CBOR_TYPE_TEXT_STRING:
1109
1.93k
    valid = dissect_cbor_text_string(tvb, pinfo, cbor_tree, offset, type_minor, ctx);
1110
1.93k
    break;
1111
5.22k
  case CBOR_TYPE_ARRAY:
1112
5.22k
    valid = dissect_cbor_array(tvb, pinfo, cbor_tree, offset, type_minor, ctx);
1113
5.22k
    break;
1114
6.02k
  case CBOR_TYPE_MAP:
1115
6.02k
    valid = dissect_cbor_map(tvb, pinfo, cbor_tree, offset, type_minor, ctx);
1116
6.02k
    break;
1117
4.83k
  case CBOR_TYPE_TAGGED:
1118
4.83k
    valid = dissect_cbor_tag(tvb, pinfo, cbor_tree, offset, type_minor, ctx);
1119
4.83k
    break;
1120
10.2k
  case CBOR_TYPE_FLOAT:
1121
10.2k
    valid = dissect_cbor_float_simple_data(tvb, pinfo, cbor_tree, offset, type_minor, ctx);
1122
10.2k
    break;
1123
0
  default:
1124
0
    DISSECTOR_ASSERT_NOT_REACHED();
1125
57.9k
  }
1126
1127
54.0k
  if (ctx) {
1128
0
    const char *item_text = cbor_diag_ctx_get(valid ? ctx : NULL, type_major);
1129
0
    if ((cbor_display_diagnostic == CBOR_DIAG_ALL)
1130
0
      || ((cbor_display_diagnostic == CBOR_DIAG_TOP) && (wmem_stack_count(ctx->stack) == 1))) {
1131
0
      proto_item_set_generated(
1132
0
        proto_tree_add_string(cbor_tree, hf_cbor_diag_text, tvb, init_offset, *offset - init_offset, item_text)
1133
0
      );
1134
0
    }
1135
1136
0
    wmem_strbuf_t *top = wmem_stack_pop(ctx->stack);
1137
0
    if (top) {
1138
0
      wmem_strbuf_append(top, item_text);
1139
1140
0
      wmem_strbuf_destroy(ctx->buf);
1141
0
    }
1142
0
    ctx->buf = top;
1143
0
  }
1144
1145
54.0k
  p_set_proto_depth(pinfo, proto_cbor, recursion_depth);
1146
54.0k
  return valid;
1147
57.9k
}
1148
1149
/** Internal dissector with context.
1150
 */
1151
static int
1152
8.82k
dissect_cbor_ctx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
1153
8.82k
  cbor_diag_ctx_t *ctx = data;
1154
8.82k
  cbor_diag_ctx_init(&ctx, pinfo->pool, false);
1155
1156
8.82k
  int         offset = 0;
1157
8.82k
  proto_item *cbor_root;
1158
8.82k
  proto_tree *cbor_tree;
1159
1160
8.82k
  cbor_root = proto_tree_add_item(tree, proto_cbor, tvb, offset, -1, ENC_NA);
1161
8.82k
  cbor_tree = proto_item_add_subtree(cbor_root, ett_cbor);
1162
1163
8.82k
  dissect_cbor_main_type(tvb, pinfo, cbor_tree, &offset, ctx);
1164
1165
8.82k
  proto_item_set_len(cbor_root, offset);
1166
8.82k
  return offset;
1167
8.82k
}
1168
1169
/** External dissector ignoring user data.
1170
 */
1171
static int
1172
8.82k
dissect_cbor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
1173
8.82k
  return dissect_cbor_ctx(tvb, pinfo, tree, NULL);
1174
8.82k
}
1175
1176
static int
1177
207
dissect_cborseq_ctx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
1178
207
  cbor_diag_ctx_t *ctx = data;
1179
207
  cbor_diag_ctx_init(&ctx, pinfo->pool, true);
1180
1181
207
  int         offset = 0;
1182
207
  proto_item *cbor_root;
1183
207
  proto_tree *cbor_tree;
1184
1185
207
  cbor_root = proto_tree_add_item(tree, proto_cbor, tvb, offset, -1, ENC_NA);
1186
207
  proto_item_append_text(cbor_root, " Sequence");
1187
207
  cbor_tree = proto_item_add_subtree(cbor_root, ett_cbor);
1188
1189
207
  unsigned count = 0;
1190
7.39k
  while ((unsigned)offset < tvb_reported_length(tvb)) {
1191
7.30k
    if (ctx && (offset != 0)) {
1192
0
      wmem_strbuf_append(ctx->buf, ", ");
1193
0
    }
1194
1195
7.30k
    if (!dissect_cbor_main_type(tvb, pinfo, cbor_tree, &offset, ctx)) {
1196
118
      break;
1197
118
    }
1198
7.18k
    ++count;
1199
7.18k
  }
1200
1201
207
  proto_item_set_generated(
1202
207
    proto_tree_add_uint64(cbor_tree, hf_cbor_seq_len, tvb, 0, offset, count)
1203
207
  );
1204
1205
207
  if (ctx && (cbor_display_diagnostic != CBOR_DIAG_NONE)) {
1206
0
    const char *item_text = cbor_diag_ctx_get(ctx, CBOR_TYPE_ARRAY);
1207
    // show for top sequence
1208
0
    proto_item_set_generated(
1209
0
      proto_tree_add_string(cbor_tree, hf_cbor_diag_text, tvb, 0, offset, item_text)
1210
0
    );
1211
0
  }
1212
1213
207
  proto_item_set_len(cbor_root, offset);
1214
207
  return offset;
1215
207
}
1216
1217
/** External dissector ignoring user data.
1218
 */
1219
static int
1220
207
dissect_cborseq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
1221
207
  return dissect_cborseq_ctx(tvb, pinfo, tree, NULL);
1222
207
}
1223
1224
/** Internal heuristic dissector which uses user data context.
1225
 */
1226
static bool
1227
0
cbor_ctx_heuristic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
1228
0
  cbor_diag_ctx_t *ctx = data;
1229
  // do not create one if not already present
1230
1231
0
  int offset = 0;
1232
0
  volatile int count = 0;
1233
1234
0
  while ((unsigned)offset < tvb_reported_length(tvb)) {
1235
0
    volatile bool valid = false;
1236
0
    TRY {
1237
0
      valid = wscbor_skip_next_item(pinfo->pool, tvb, &offset);
1238
0
    }
1239
0
    CATCH_BOUNDS_AND_DISSECTOR_ERRORS {}
1240
0
    ENDTRY;
1241
0
    if (!valid) {
1242
      // A failure in any one item is a failure of the heuristic
1243
0
      count = 0;
1244
0
      break;
1245
0
    }
1246
0
    ++count;
1247
0
  }
1248
1249
  // Anything went wrong with any part of the data
1250
0
  if ((count == 0) || ((unsigned)offset != tvb_reported_length(tvb))) {
1251
0
    return false;
1252
0
  }
1253
1254
0
  if (ctx) {
1255
0
    wmem_strbuf_append(ctx->buf, "<<");
1256
0
  }
1257
1258
0
  if (count == 1) {
1259
0
    dissect_cbor_ctx(tvb, pinfo, tree, ctx);
1260
0
  }
1261
0
  else {
1262
0
    dissect_cborseq_ctx(tvb, pinfo, tree, ctx);
1263
0
  }
1264
1265
0
  if (ctx) {
1266
0
    wmem_strbuf_append(ctx->buf, ">>");
1267
0
  }
1268
1269
0
  return true;
1270
0
}
1271
1272
bool
1273
0
cbor_heuristic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
1274
0
  return cbor_ctx_heuristic(tvb, pinfo, tree, NULL);
1275
0
}
1276
1277
void
1278
proto_register_cbor(void)
1279
16
{
1280
16
  static hf_register_info hf[] = {
1281
16
    { &hf_cbor_item_major_type,
1282
16
      { "Major Type", "cbor.item.major_type",
1283
16
        FT_UINT8, BASE_DEC, VALS(major_type_vals), 0xe0,
1284
16
        NULL, HFILL }
1285
16
    },
1286
16
    { &hf_cbor_item_integer_size,
1287
16
      { "Size", "cbor.item.size",
1288
16
        FT_UINT8, BASE_DEC, VALS(integer_size_vals), 0x1f,
1289
16
        NULL, HFILL }
1290
16
    },
1291
16
    { &hf_cbor_item_length_size,
1292
16
      { "Size", "cbor.item.size",
1293
16
        FT_UINT8, BASE_DEC, VALS(length_size_vals), 0x1f,
1294
16
        NULL, HFILL }
1295
16
    },
1296
16
    { &hf_cbor_item_length5,
1297
16
      { "Length", "cbor.item.length5",
1298
16
        FT_UINT8, BASE_DEC, NULL, 0x1f,
1299
16
        NULL, HFILL }
1300
16
    },
1301
16
    { &hf_cbor_item_length,
1302
16
      { "Length", "cbor.item.length",
1303
16
        FT_UINT64, BASE_DEC, NULL, 0x00,
1304
16
        NULL, HFILL }
1305
16
    },
1306
16
    { &hf_cbor_item_items5,
1307
16
      { "Items", "cbor.item.items5",
1308
16
        FT_UINT8, BASE_DEC, NULL, 0x1f,
1309
16
        NULL, HFILL }
1310
16
    },
1311
16
    { &hf_cbor_item_items,
1312
16
      { "Items", "cbor.item.items",
1313
16
        FT_UINT64, BASE_DEC, NULL, 0x00,
1314
16
        NULL, HFILL }
1315
16
    },
1316
16
    { &hf_cbor_item_pairs5,
1317
16
      { "Pairs", "cbor.item.pairs",
1318
16
        FT_UINT8, BASE_DEC, NULL, 0x1f,
1319
16
        NULL, HFILL }
1320
16
    },
1321
16
    { &hf_cbor_item_pairs,
1322
16
      { "Pairs", "cbor.item.pairs",
1323
16
        FT_UINT64, BASE_DEC, NULL, 0x00,
1324
16
        NULL, HFILL }
1325
16
    },
1326
16
    { &hf_cbor_item_float_simple_type,
1327
16
      { "Type", "cbor.item.float_simple_type",
1328
16
        FT_UINT8, BASE_DEC, VALS(float_simple_type_vals), 0x1f,
1329
16
        NULL, HFILL }
1330
16
    },
1331
16
    { &hf_cbor_item_unsigned_integer,
1332
16
      { "Unsigned Integer", "cbor.item.unsigned_integer",
1333
16
        FT_NONE, BASE_NONE, NULL, 0x00,
1334
16
        NULL, HFILL }
1335
16
    },
1336
16
    { &hf_cbor_item_negative_integer,
1337
16
      { "Negative Integer", "cbor.item.negative_integer",
1338
16
        FT_NONE, BASE_NONE, NULL, 0x00,
1339
16
        NULL, HFILL }
1340
16
    },
1341
16
    { &hf_cbor_item_text_string,
1342
16
      { "Text String", "cbor.item.textstring",
1343
16
        FT_NONE, BASE_NONE, NULL, 0x00,
1344
16
        NULL, HFILL }
1345
16
    },
1346
16
    { &hf_cbor_item_byte_string,
1347
16
      { "Byte String", "cbor.item.bytestring",
1348
16
        FT_NONE, BASE_NONE, NULL, 0x00,
1349
16
        NULL, HFILL }
1350
16
    },
1351
16
    { &hf_cbor_item_array,
1352
16
      { "Array", "cbor.item.array",
1353
16
        FT_NONE, BASE_NONE, NULL, 0x00,
1354
16
        NULL, HFILL }
1355
16
    },
1356
16
    { &hf_cbor_item_map,
1357
16
      { "Map", "cbor.item.map",
1358
16
        FT_NONE, BASE_NONE, NULL, 0x00,
1359
16
        NULL, HFILL }
1360
16
    },
1361
16
    { &hf_cbor_item_tag,
1362
16
      { "Tag", "cbor.item.tag",
1363
16
        FT_NONE, BASE_NONE, NULL, 0x00,
1364
16
        NULL, HFILL }
1365
16
    },
1366
16
    { &hf_cbor_item_float_simple,
1367
16
      { "Floating-point or Simple", "cbor.item.float_or_simple",
1368
16
        FT_NONE, BASE_NONE, NULL, 0x00,
1369
16
        NULL, HFILL }
1370
16
    },
1371
16
    { &hf_cbor_type_uint5,
1372
16
      { "Unsigned Integer", "cbor.type.uint",
1373
16
        FT_UINT8, BASE_DEC, NULL, 0x1f,
1374
16
        NULL, HFILL }
1375
16
    },
1376
16
    { &hf_cbor_type_uint,
1377
16
      { "Unsigned Integer", "cbor.type.uint",
1378
16
        FT_UINT64, BASE_DEC, NULL, 0x00,
1379
16
        NULL, HFILL }
1380
16
    },
1381
16
    { &hf_cbor_type_nint,
1382
16
      { "Negative Integer", "cbor.type.nint",
1383
16
        FT_INT64, BASE_DEC, NULL, 0x00,
1384
16
        NULL, HFILL }
1385
16
    },
1386
16
    { &hf_cbor_type_byte_string,
1387
16
      { "Byte String", "cbor.type.bytestring",
1388
16
        FT_BYTES, BASE_NONE, NULL, 0x00,
1389
16
        NULL, HFILL }
1390
16
    },
1391
16
    { &hf_cbor_type_byte_string_indef,
1392
16
      { "Byte String (indefinite length)", "cbor.type.bytestring.indef",
1393
16
        FT_NONE, BASE_NONE, NULL, 0x0,
1394
16
        NULL, HFILL }
1395
16
    },
1396
16
    { &hf_cbor_type_text_string,
1397
16
      { "Text String", "cbor.type.textstring",
1398
16
        FT_STRING, BASE_NONE, NULL, 0x00,
1399
16
        NULL, HFILL }
1400
16
    },
1401
16
    { &hf_cbor_type_text_string_indef,
1402
16
      { "Text String (indefinite length)", "cbor.type.textstring.indef",
1403
16
        FT_NONE, BASE_NONE, NULL, 0x0,
1404
16
        NULL, HFILL }
1405
16
    },
1406
16
    { &hf_cbor_type_tag,
1407
16
      { "Tag", "cbor.type.tag",
1408
16
        FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(tag64_vals), 0x00,
1409
16
        NULL, HFILL }
1410
16
    },
1411
16
    { &hf_cbor_type_simple_data5,
1412
16
      { "Simple data", "cbor.type.simple_data",
1413
16
        FT_UINT8, BASE_DEC, VALS(vals_simple_data), 0x1f,
1414
16
        NULL, HFILL }
1415
16
    },
1416
16
    { &hf_cbor_type_simple_data8,
1417
16
      { "Simple data", "cbor.type.simple_data",
1418
16
        FT_UINT8, BASE_DEC, VALS(vals_simple_data), 0x00,
1419
16
        NULL, HFILL }
1420
16
    },
1421
16
    { &hf_cbor_type_float16,
1422
16
      { "Float 16 Bit", "cbor.type.float16",
1423
16
        FT_FLOAT, BASE_NONE, NULL, 0x00,
1424
16
        NULL, HFILL }
1425
16
    },
1426
16
    { &hf_cbor_type_float32,
1427
16
      { "Float 32 Bit", "cbor.type.float32",
1428
16
        FT_FLOAT, BASE_NONE, NULL, 0x00,
1429
16
        NULL, HFILL }
1430
16
    },
1431
16
    { &hf_cbor_type_float64,
1432
16
      { "Float 64 Bit", "cbor.type.float64",
1433
16
        FT_DOUBLE, BASE_NONE, NULL, 0x00,
1434
16
        NULL, HFILL }
1435
16
    },
1436
16
    { &hf_cbor_seq_len,
1437
16
      { "Sequence length", "cbor.seq_len",
1438
16
        FT_UINT64, BASE_DEC, NULL, 0x00,
1439
16
        "Number of items in the sequence", HFILL }
1440
16
    },
1441
16
    { &hf_cbor_diag_text,
1442
16
      { "Diagnostic Notation", "cbor.diagnostic",
1443
16
        FT_STRINGZ, BASE_NONE, NULL, 0x00,
1444
16
        "CBOR extended diagnostic notation of preceding data", HFILL }
1445
16
    },
1446
16
  };
1447
1448
16
  static int *ett[] = {
1449
16
    &ett_cbor,
1450
16
    &ett_cbor_type,
1451
16
    &ett_cbor_unsigned_integer,
1452
16
    &ett_cbor_negative_integer,
1453
16
    &ett_cbor_byte_string,
1454
16
    &ett_cbor_byte_string_indef,
1455
16
    &ett_cbor_text_string,
1456
16
    &ett_cbor_text_string_indef,
1457
16
    &ett_cbor_array,
1458
16
    &ett_cbor_map,
1459
16
    &ett_cbor_tag,
1460
16
    &ett_cbor_float_simple
1461
16
  };
1462
1463
16
  static ei_register_info ei[] = {
1464
16
    { &ei_cbor_invalid_minor_type,
1465
16
      { "cbor.invalid_minor_type", PI_MALFORMED, PI_WARN, "Invalid minor type", EXPFILL }},
1466
16
    { &ei_cbor_invalid_element,
1467
16
      { "cbor.invalid_element", PI_MALFORMED, PI_WARN, "Invalid element", EXPFILL }},
1468
16
    { &ei_cbor_too_long_length,
1469
16
      { "cbor.too_long_length", PI_MALFORMED, PI_WARN, "Too long length", EXPFILL }},
1470
16
    { &ei_cbor_max_recursion_depth_reached,
1471
16
      { "cbor.max_recursion_depth_reached", PI_PROTOCOL, PI_WARN, "Maximum allowed recursion depth reached. Dissection stopped.", EXPFILL }},
1472
16
    { &ei_cbor_embedded_bstr,
1473
16
      { "cbor.embedded_bstr", PI_COMMENTS_GROUP, PI_COMMENT, "Heuristic dissection of data in a byte string", EXPFILL }},
1474
16
  };
1475
1476
16
  expert_module_t *expert_cbor;
1477
1478
16
  proto_cbor = proto_register_protocol("Concise Binary Object Representation", "CBOR", "cbor");
1479
16
  proto_register_field_array(proto_cbor, hf, array_length(hf));
1480
16
  proto_register_subtree_array(ett, array_length(ett));
1481
16
  expert_cbor = expert_register_protocol(proto_cbor);
1482
16
  expert_register_field_array(expert_cbor, ei, array_length(ei));
1483
1484
16
  cbor_handle = register_dissector("cbor", dissect_cbor, proto_cbor);
1485
16
  cborseq_handle = register_dissector_with_description("cborseq", "CBOR Sequence", dissect_cborseq, proto_cbor);
1486
1487
16
  module_t *module_cbor = prefs_register_protocol(proto_cbor, NULL);
1488
16
  prefs_register_bool_preference(
1489
16
      module_cbor,
1490
16
      "dissect_embeded_bstr",  /* mispelt but best leave */
1491
16
      "Attempt heuristic dissection of byte strings",
1492
16
      "If enabled, a heuristic dissection of byte string contents is performed.",
1493
16
      &cbor_dissect_embeded_bstr
1494
16
  );
1495
16
  prefs_register_enum_preference(
1496
16
      module_cbor,
1497
16
      "display_diagnostic",
1498
16
      "Display CBOR diagnostic notation",
1499
16
      "If enabled, a field is added to the topmost CBOR tree to display the data "
1500
16
      "in CBOR extended diagnostic notation (EDN) text.",
1501
16
      &cbor_display_diagnostic,
1502
16
      cbor_display_diagnostic_choices,
1503
      false // radio buttons
1504
16
  );
1505
16
  prefs_register_bool_preference(
1506
16
      module_cbor,
1507
16
      "diagnostic_bstr_text",
1508
16
      "Diagnostic byte strings as text",
1509
16
      "If enabled, a diagnostic display of byte string values which contain only "
1510
16
      "UTF-8 text will be displayed as text without a quote prefix.",
1511
16
      &cbor_diagnostic_bstr_text
1512
16
  );
1513
1514
16
  cbor_bstr_heur = register_heur_dissector_list_with_description("cbor.bstr", "CBOR byte string content", proto_cbor);
1515
16
}
1516
1517
void
1518
proto_reg_handoff_cbor(void)
1519
16
{
1520
16
  dissector_add_string("media_type", "application/cbor", cbor_handle); /* RFC 8949 */
1521
16
  dissector_add_string("media_type", "application/cwt", cbor_handle); /* RFC 8392 */
1522
16
  dissector_add_string("media_type", "application/cbor-seq", cborseq_handle); /* RFC 8742 */
1523
1524
16
  dissector_add_string("media_type.suffix", "cbor", cbor_handle); /* RFC 8949 */
1525
16
  dissector_add_string("media_type.suffix", "cbor-seq", cborseq_handle); /* RFC 8742 */
1526
1527
16
  heur_dissector_add("http", cbor_heuristic, "CBOR over HTTP", "cbor_http", proto_cbor, HEURISTIC_DISABLE);
1528
  // register for CBOR-in-CBOR heuristic
1529
16
  heur_dissector_add("cbor.bstr", cbor_ctx_heuristic, "CBOR in CBOR byte string", "cbor_cbor", proto_cbor, HEURISTIC_ENABLE);
1530
16
}
1531
1532
/*
1533
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1534
 *
1535
 * Local variables:
1536
 * c-basic-offset: 8
1537
 * tab-width: 8
1538
 * indent-tabs-mode: t
1539
 * End:
1540
 *
1541
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1542
 * :indentSize=8:tabSize=8:noTabs=false:
1543
 */