wireshark/epan/dissectors/packet-cbor.c

893 lines
25 KiB
C

/* packet-cbor.c
* Routines for Concise Binary Object Representation (CBOR) (RFC 7049) dissection
* References:
* RFC 7049: https://tools.ietf.org/html/rfc7049
* RFC 8742: https://tools.ietf.org/html/rfc8742
*
* Copyright 2015, Hauke Mehrtens <hauke@hauke-m.de>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <math.h>
#include <epan/packet.h>
#include <epan/expert.h>
void proto_register_cbor(void);
void proto_reg_handoff_cbor(void);
static int proto_cbor = -1;
static int hf_cbor_type_uints = -1;
static int hf_cbor_type_uint8 = -1;
static int hf_cbor_type_uint16 = -1;
static int hf_cbor_type_uint32 = -1;
static int hf_cbor_type_uint64 = -1;
static int hf_cbor_type_nint = -1;
static int hf_cbor_type_byte_string = -1;
static int hf_cbor_type_byte_string_undef = -1;
static int hf_cbor_type_text_string = -1;
static int hf_cbor_type_text_string_undef = -1;
static int hf_cbor_type_array = -1;
static int hf_cbor_type_map = -1;
static int hf_cbor_type_tags = -1;
static int hf_cbor_type_tag8 = -1;
static int hf_cbor_type_tag16 = -1;
static int hf_cbor_type_tag32 = -1;
static int hf_cbor_type_tag64 = -1;
static int hf_cbor_type_simple_datas = -1;
static int hf_cbor_type_simple_data8 = -1;
static int hf_cbor_type_float16 = -1;
static int hf_cbor_type_float32 = -1;
static int hf_cbor_type_float64 = -1;
static gint ett_cbor = -1;
static gint ett_cbor_byte_string_undef = -1;
static gint ett_cbor_text_string_undef = -1;
static gint ett_cbor_array = -1;
static gint ett_cbor_map = -1;
static gint ett_cbor_map_entry = -1;
static gint ett_cbor_tag = -1;
static expert_field ei_cbor_invalid_minor_type = EI_INIT;
static expert_field ei_cbor_invalid_element = EI_INIT;
static expert_field ei_cbor_too_long_length = EI_INIT;
static dissector_handle_t cbor_handle;
static dissector_handle_t cborseq_handle;
#define CBOR_TYPE_USIGNED_INT 0
#define CBOR_TYPE_NEGATIVE_INT 1
#define CBOR_TYPE_BYTE_STRING 2
#define CBOR_TYPE_TEXT_STRING 3
#define CBOR_TYPE_ARRAY 4
#define CBOR_TYPE_MAP 5
#define CBOR_TYPE_TAGGED 6
#define CBOR_TYPE_FLOAT 7
/* see https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml#tags */
static const value_string vals_tags[] = {
{ 0, "Standard date/time string" },
{ 1, "Epoch-based date/time" },
{ 2, "Positive bignum" },
{ 3, "Negative bignum" },
{ 4, "Decimal fraction" },
{ 5, "Bigfloat" },
{ 21, "Expected conversion to base64url encoding" },
{ 22, "Expected conversion to base64 encoding" },
{ 23, "Expected conversion to base16 encoding" },
{ 24, "Encoded CBOR data item" },
{ 25, "reference the nth previously seen string" },
{ 26, "Serialised Perl object with classname and constructor arguments" },
{ 27, "Serialised language-independent object with type name and constructor arguments" },
{ 28, "mark value as (potentially) shared" },
{ 29, "reference nth marked value" },
{ 30, "Rational number" },
{ 32, "URI" },
{ 33, "base64url" },
{ 34, "base64" },
{ 35, "Regular expression" },
{ 36, "MIME message" },
{ 37, "Binary UUID" },
{ 38, "Language-tagged string" },
{ 39, "Identifier" },
{ 256, "mark value as having string references" },
{ 257, "Binary MIME message" },
{ 264, "Decimal fraction with arbitrary exponent" },
{ 265, "Bigfloat with arbitrary exponent" },
{ 22098, "hint that indicates an additional level of indirection" },
{ 55799, "Self-describe CBOR" },
{ 0, NULL },
};
static const val64_string vals64_tags[] = {
{ 0, "Standard date/time string" },
{ 1, "Epoch-based date/time" },
{ 2, "Positive bignum" },
{ 3, "Negative bignum" },
{ 4, "Decimal fraction" },
{ 5, "Bigfloat" },
{ 21, "Expected conversion to base64url encoding" },
{ 22, "Expected conversion to base64 encoding" },
{ 23, "Expected conversion to base16 encoding" },
{ 24, "Encoded CBOR data item" },
{ 25, "reference the nth previously seen string" },
{ 26, "Serialised Perl object with classname and constructor arguments" },
{ 27, "Serialised language-independent object with type name and constructor arguments" },
{ 28, "mark value as (potentially) shared" },
{ 29, "reference nth marked value" },
{ 30, "Rational number" },
{ 32, "URI" },
{ 33, "base64url" },
{ 34, "base64" },
{ 35, "Regular expression" },
{ 36, "MIME message" },
{ 37, "Binary UUID" },
{ 38, "Language-tagged string" },
{ 39, "Identifier" },
{ 256, "mark value as having string references" },
{ 257, "Binary MIME message" },
{ 264, "Decimal fraction with arbitrary exponent" },
{ 265, "Bigfloat with arbitrary exponent" },
{ 22098, "hint that indicates an additional level of indirection" },
{ 55799, "Self-describe CBOR" },
{ 0, NULL },
};
static const value_string vals_simple_data[] = {
{ 20, "False" },
{ 21, "True" },
{ 22, "null" },
{ 23, "Undefined value" },
{ 0, NULL },
};
static proto_item *
dissect_cbor_main_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, gint *offset);
static proto_item *
dissect_cbor_unsigned_integer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, gint *offset, guint8 type_minor)
{
proto_item *item;
switch (type_minor) {
case 0x18:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_uint8, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
return item;
case 0x19:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_uint16, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
return item;
case 0x1a:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_uint32, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
return item;
case 0x1b:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_uint64, tvb, *offset, 8, ENC_BIG_ENDIAN);
*offset += 8;
return item;
default:
if (type_minor <= 0x17) {
item = proto_tree_add_item(cbor_tree, hf_cbor_type_uints, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
return item;
}
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_invalid_minor_type,
"invalid minor type %i in unsigned integer", type_minor);
return NULL;
}
}
static proto_item *
dissect_cbor_negative_integer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, gint *offset, guint8 type_minor)
{
gint64 value;
proto_item *item;
switch (type_minor) {
case 0x18:
*offset += 1;
value = (gint64)-1 - tvb_get_guint8(tvb, *offset);
item = proto_tree_add_int64(cbor_tree, hf_cbor_type_nint, tvb, *offset, 1, value);
*offset += 1;
return item;
case 0x19:
*offset += 1;
value = (gint64)-1 - tvb_get_ntohs(tvb, *offset);
item = proto_tree_add_int64(cbor_tree, hf_cbor_type_nint, tvb, *offset, 2, value);
*offset += 2;
return item;
case 0x1a:
*offset += 1;
value = (gint64)-1 - tvb_get_ntohl(tvb, *offset);
item = proto_tree_add_int64(cbor_tree, hf_cbor_type_nint, tvb, *offset, 4, value);
*offset += 4;
return item;
case 0x1b:
*offset += 1;
/* TODO: an overflow could happen here, for negative int < G_MININT64 */
value = (gint64)-1 - tvb_get_ntoh64(tvb, *offset);
if (value > -1) {
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_too_long_length,
"The value is too small, we can not display it correctly");
}
item = proto_tree_add_int64(cbor_tree, hf_cbor_type_nint, tvb, *offset, 8, value);
*offset += 8;
return item;
default:
if (type_minor <= 0x17) {
value = -1 - type_minor;
item = proto_tree_add_int64(cbor_tree, hf_cbor_type_nint, tvb, *offset, 1, value);
*offset += 1;
return item;
}
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_invalid_minor_type,
"invalid minor type %i in negative integer", type_minor);
return NULL;
}
}
static proto_item *
dissect_cbor_byte_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, gint *offset, guint8 type_minor)
{
guint64 length;
gint eof_type;
proto_tree *subtree;
proto_item *item;
proto_item *elem;
switch (type_minor) {
case 0x18:
*offset += 1;
length = tvb_get_guint8(tvb, *offset);
*offset += 1;
break;
case 0x19:
*offset += 1;
length = tvb_get_ntohs(tvb, *offset);
*offset += 2;
break;
case 0x1a:
*offset += 1;
length = tvb_get_ntohl(tvb, *offset);
*offset += 4;
break;
case 0x1b:
*offset += 1;
length = tvb_get_ntoh64(tvb, *offset);
*offset += 8;
break;
case 0x1f:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_byte_string_undef, tvb, *offset, 1, ENC_NA);
subtree = proto_item_add_subtree(item, ett_cbor_byte_string_undef);
while (1)
{
eof_type = tvb_get_guint8(tvb, *offset);
if (eof_type == 0xff) {
*offset += 1;
proto_item_set_end(item, tvb, *offset);
return item;
}
if (((eof_type & 0xe0) >> 5) != CBOR_TYPE_BYTE_STRING) {
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_invalid_element,
"invalid element %i, expected byte string", (eof_type & 0xe0) >> 5);
return NULL;
}
elem = dissect_cbor_byte_string(tvb, pinfo, subtree, offset, eof_type & 0x1f);
if (!elem)
return NULL;
}
DISSECTOR_ASSERT_NOT_REACHED();
return item;
default:
if (type_minor <= 0x17) {
length = type_minor;
*offset += 1;
break;
}
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_invalid_minor_type,
"invalid minor type %i in byte string", type_minor);
return NULL;
}
if (length > G_MAXINT32 || *offset + (gint)length < *offset) {
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_too_long_length,
"the length (%" G_GUINT64_FORMAT ") of the byte string too long", length);
return NULL;
}
item = proto_tree_add_item(cbor_tree, hf_cbor_type_byte_string, tvb, *offset, (gint)length, ENC_BIG_ENDIAN|ENC_NA);
*offset += (gint)length;
return item;
}
static proto_item *
dissect_cbor_text_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, gint *offset, guint8 type_minor)
{
guint64 length = 0;
gint eof_type;
proto_tree *subtree;
proto_item *item;
proto_item *elem;
switch (type_minor) {
case 0x18:
*offset += 1;
length = tvb_get_guint8(tvb, *offset);
*offset += 1;
break;
case 0x19:
*offset += 1;
length = tvb_get_ntohs(tvb, *offset);
*offset += 2;
break;
case 0x1a:
*offset += 1;
length = tvb_get_ntohl(tvb, *offset);
*offset += 4;
break;
case 0x1b:
*offset += 1;
length = tvb_get_ntoh64(tvb, *offset);
*offset += 8;
break;
case 0x1f:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_text_string_undef, tvb, *offset, 1, ENC_NA);
subtree = proto_item_add_subtree(item, ett_cbor_text_string_undef);
while (1)
{
eof_type = tvb_get_guint8(tvb, *offset);
if (eof_type == 0xff) {
*offset += 1;
proto_item_set_end(item, tvb, *offset);
return item;
}
if (((eof_type & 0xe0) >> 5) != CBOR_TYPE_TEXT_STRING) {
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_invalid_element,
"invalid element %i, expected text string", (eof_type & 0xe0) >> 5);
return NULL;
}
elem = dissect_cbor_text_string(tvb, pinfo, subtree, offset, eof_type & 0x1f);
if (!elem)
return NULL;
}
DISSECTOR_ASSERT_NOT_REACHED();
return item;
default:
if (type_minor <= 0x17) {
length = type_minor;
*offset += 1;
break;
}
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_invalid_minor_type,
"invalid minor type %i in text string", type_minor);
return NULL;
}
if (length > G_MAXINT32 || *offset + (gint)length < *offset) {
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_too_long_length,
"the length (%" G_GUINT64_FORMAT ") of the text string too long", length);
return NULL;
}
item = proto_tree_add_item(cbor_tree, hf_cbor_type_text_string, tvb, *offset, (gint)length, ENC_BIG_ENDIAN|ENC_UTF_8);
*offset += (gint)length;
return item;
}
static proto_item *
dissect_cbor_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, gint *offset, guint8 type_minor)
{
guint64 length = 0;
guint64 i;
gint orig_offset = *offset;
proto_tree *subtree;
proto_item *item;
proto_item *elem;
gboolean eof = 0;
switch (type_minor) {
case 0x18:
*offset += 1;
length = tvb_get_guint8(tvb, *offset);
*offset += 1;
break;
case 0x19:
*offset += 1;
length = tvb_get_ntohs(tvb, *offset);
*offset += 2;
break;
case 0x1a:
*offset += 1;
length = tvb_get_ntohl(tvb, *offset);
*offset += 4;
break;
case 0x1b:
*offset += 1;
length = tvb_get_ntoh64(tvb, *offset);
*offset += 8;
break;
case 0x1f:
*offset += 1;
length = INT_MAX;
eof = 1;
break;
default:
if (type_minor <= 0x17) {
length = type_minor;
*offset += 1;
break;
}
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_invalid_minor_type,
"invalid minor type %i in array", type_minor);
return NULL;
}
if (eof) {
item = proto_tree_add_string_format_value(cbor_tree, hf_cbor_type_array,
tvb, orig_offset, -1, "Array", "(undefined elements)");
} else {
item = proto_tree_add_string_format_value(cbor_tree, hf_cbor_type_array,
tvb, orig_offset, -1, "Array", "(%"G_GINT64_MODIFIER"u elements)", length);
}
subtree = proto_item_add_subtree(item, ett_cbor_array);
for (i = 0; i < length; i++)
{
if (eof) {
gint value = tvb_get_guint8(tvb, *offset);
if (value == 0xff) {
*offset += 1;
break;
}
}
elem = dissect_cbor_main_type(tvb, pinfo, subtree, offset);
if (!elem)
return NULL;
}
proto_item_set_end(item, tvb, *offset);
return item;
}
static proto_item *
dissect_cbor_map(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, gint *offset, guint8 type_minor)
{
guint64 length = 0;
guint64 i;
gint orig_offset = *offset;
proto_tree *subtree;
proto_item *item;
gboolean eof = 0;
proto_tree *key_tree;
proto_item *key;
switch (type_minor) {
case 0x18:
*offset += 1;
length = tvb_get_guint8(tvb, *offset);
*offset += 1;
break;
case 0x19:
*offset += 1;
length = tvb_get_ntohs(tvb, *offset);
*offset += 2;
break;
case 0x1a:
*offset += 1;
length = tvb_get_ntohl(tvb, *offset);
*offset += 4;
break;
case 0x1b:
*offset += 1;
length = tvb_get_ntoh64(tvb, *offset);
*offset += 8;
break;
case 0x1f:
*offset += 1;
length = INT_MAX;
eof = 1;
break;
default:
if (type_minor <= 0x17) {
length = type_minor;
*offset += 1;
break;
}
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_invalid_minor_type,
"invalid minor type %i in map", type_minor);
return NULL;
}
if (eof) {
item = proto_tree_add_string_format_value(cbor_tree, hf_cbor_type_map,
tvb, orig_offset, -1, "Map", "(undefined entries)");
} else {
item = proto_tree_add_string_format_value(cbor_tree, hf_cbor_type_map,
tvb, orig_offset, -1, "Map", "(%"G_GINT64_MODIFIER"u entries)", length);
}
subtree = proto_item_add_subtree(item, ett_cbor_map);
for (i = 0; i < length; i++)
{
if (eof) {
gint value = tvb_get_guint8(tvb, *offset);
if (value == 0xff) {
*offset += 1;
break;
}
}
key = dissect_cbor_main_type(tvb, pinfo, subtree, offset);
if (!key)
return NULL;
key_tree = proto_item_add_subtree(key, ett_cbor_map_entry);
key = dissect_cbor_main_type(tvb, pinfo, key_tree, offset);
if (!key)
return NULL;
}
proto_item_set_end(item, tvb, *offset);
return item;
}
static proto_item *
dissect_cbor_tag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, gint *offset, guint8 type_minor)
{
proto_item *item;
proto_item *tagged;
proto_tree *tagged_tree;
switch (type_minor) {
case 0x18:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_tag8, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
break;
case 0x19:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_tag16, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
break;
case 0x1a:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_tag32, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
break;
case 0x1b:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_tag64, tvb, *offset, 8, ENC_BIG_ENDIAN);
*offset += 8;
break;
default:
if (type_minor <= 0x17) {
item = proto_tree_add_item(cbor_tree, hf_cbor_type_tags, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
break;
}
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_invalid_minor_type,
"invalid minor type %i in tag", type_minor);
return NULL;
}
tagged_tree = proto_item_add_subtree(item, ett_cbor_tag);
tagged = dissect_cbor_main_type(tvb, pinfo, tagged_tree, offset);
if (!tagged)
return NULL;
return item;
}
/* based on code from rfc7049 appendix-D */
static proto_item *decode_half(tvbuff_t *tvb, proto_tree *tree, gint *offset, int hfindex) {
int half, exponent, mantissa;
float val;
proto_item *item;
half = tvb_get_ntohs(tvb, *offset);
exponent = (half >> 10) & 0x1f;
mantissa = half & 0x3ff;
if (exponent == 0) {
val = ldexpf((float)mantissa, -24);
item = proto_tree_add_float(tree, hfindex, tvb, *offset, 2,
half & 0x8000 ? -val : val);
} else if (exponent != 31) {
val = ldexpf((float)(mantissa + 1024), exponent - 25);
item = proto_tree_add_float(tree, hfindex, tvb, *offset, 2,
half & 0x8000 ? -val : val);
} else {
item = proto_tree_add_float_format_value(tree, hfindex, tvb, *offset, 2,
0, "%s", mantissa == 0 ? "INFINITY" : "NAN");
}
*offset += 2;
return item;
}
static proto_item *
dissect_cbor_float_simple_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, gint *offset, guint8 type_minor)
{
proto_item *item;
switch (type_minor) {
case 0x18:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_simple_data8, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
return item;
case 0x19:
*offset += 1;
item = decode_half(tvb, cbor_tree, offset, hf_cbor_type_float16);
return item;
case 0x1a:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_float32, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
return item;
case 0x1b:
*offset += 1;
item = proto_tree_add_item(cbor_tree, hf_cbor_type_float64, tvb, *offset, 8, ENC_BIG_ENDIAN);
*offset += 8;
return item;
default:
if (type_minor <= 0x17) {
item = proto_tree_add_item(cbor_tree, hf_cbor_type_simple_datas, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
return item;
}
expert_add_info_format(pinfo, cbor_tree, &ei_cbor_invalid_minor_type,
"invalid minor type %i in simple data and float", type_minor);
return NULL;
}
}
static proto_item *
dissect_cbor_main_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, gint *offset)
{
guint8 type;
guint8 type_major;
guint8 type_minor;
type = tvb_get_guint8(tvb, *offset);
type_major = (type & 0xe0) >> 5;
type_minor = (type & 0x1f);
switch (type_major) {
case CBOR_TYPE_USIGNED_INT:
return dissect_cbor_unsigned_integer(tvb, pinfo, cbor_tree, offset, type_minor);
case CBOR_TYPE_NEGATIVE_INT:
return dissect_cbor_negative_integer(tvb, pinfo, cbor_tree, offset, type_minor);
case CBOR_TYPE_BYTE_STRING:
return dissect_cbor_byte_string(tvb, pinfo, cbor_tree, offset, type_minor);
case CBOR_TYPE_TEXT_STRING:
return dissect_cbor_text_string(tvb, pinfo, cbor_tree, offset, type_minor);
case CBOR_TYPE_ARRAY:
return dissect_cbor_array(tvb, pinfo, cbor_tree, offset, type_minor);
case CBOR_TYPE_MAP:
return dissect_cbor_map(tvb, pinfo, cbor_tree, offset, type_minor);
case CBOR_TYPE_TAGGED:
return dissect_cbor_tag(tvb, pinfo, cbor_tree, offset, type_minor);
case CBOR_TYPE_FLOAT:
return dissect_cbor_float_simple_data(tvb, pinfo, cbor_tree, offset, type_minor);
}
DISSECTOR_ASSERT_NOT_REACHED();
return NULL;
}
static int
dissect_cbor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
{
gint offset = 0;
proto_item *cbor_root;
proto_tree *cbor_tree;
cbor_root = proto_tree_add_item(parent_tree, proto_cbor, tvb, offset, -1, ENC_NA);
cbor_tree = proto_item_add_subtree(cbor_root, ett_cbor);
dissect_cbor_main_type(tvb, pinfo, cbor_tree, &offset);
proto_item_set_len(cbor_root, offset);
return offset;
}
static int
dissect_cborseq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
{
gint offset = 0;
proto_item *cbor_root;
proto_tree *cbor_tree;
proto_item *elem;
cbor_root = proto_tree_add_item(parent_tree, proto_cbor, tvb, offset, -1, ENC_NA);
proto_item_append_text(cbor_root, " Sequence");
cbor_tree = proto_item_add_subtree(cbor_root, ett_cbor);
while ((guint)offset < tvb_reported_length(tvb)) {
elem = dissect_cbor_main_type(tvb, pinfo, cbor_tree, &offset);
if (!elem) {
break;
}
}
return offset;
}
void
proto_register_cbor(void)
{
static hf_register_info hf[] = {
{ &hf_cbor_type_uints,
{ "Unsigned Integer", "cbor.type.uints",
FT_UINT8, BASE_DEC, NULL, 0x1f,
NULL, HFILL }
},
{ &hf_cbor_type_uint8,
{ "Unsigned Integer", "cbor.type.uint8",
FT_UINT8, BASE_DEC, NULL, 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_uint16,
{ "Unsigned Integer", "cbor.type.uint16",
FT_UINT16, BASE_DEC, NULL, 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_uint32,
{ "Unsigned Integer", "cbor.type.uint32",
FT_UINT32, BASE_DEC, NULL, 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_uint64,
{ "Unsigned Integer", "cbor.type.uint64",
FT_UINT64, BASE_DEC, NULL, 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_nint,
{ "Negative Integer", "cbor.type.nint",
FT_INT64, BASE_DEC, NULL, 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_byte_string,
{ "Byte String", "cbor.type.bytestring",
FT_BYTES, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_byte_string_undef,
{ "Byte String (undefined length)", "cbor.type.bytestring.undef",
FT_NONE, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_cbor_type_text_string,
{ "Text String", "cbor.type.textstring",
FT_STRING, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_text_string_undef,
{ "Text String (undefined length)", "cbor.type.textstring.undef",
FT_NONE, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_cbor_type_array,
{ "Array", "cbor.type.array",
FT_STRING, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_map,
{ "Map", "cbor.type.map",
FT_STRING, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_tags,
{ "Tag", "cbor.type.tags",
FT_UINT8, BASE_DEC, VALS(vals_tags), 0x1f,
NULL, HFILL }
},
{ &hf_cbor_type_tag8,
{ "Tag", "cbor.type.tag8",
FT_UINT8, BASE_DEC, VALS(vals_tags), 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_tag16,
{ "Tag", "cbor.type.tag16",
FT_UINT16, BASE_DEC, VALS(vals_tags), 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_tag32,
{ "Tag", "cbor.type.tag32",
FT_UINT32, BASE_DEC, VALS(vals_tags), 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_tag64,
{ "Tag", "cbor.type.tag64",
FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(vals64_tags), 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_simple_datas,
{ "Simple data", "cbor.type.simple_datas",
FT_UINT8, BASE_DEC, VALS(vals_simple_data), 0x1f,
NULL, HFILL }
},
{ &hf_cbor_type_simple_data8,
{ "Simple data", "cbor.type.simple_data8",
FT_UINT8, BASE_DEC, VALS(vals_simple_data), 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_float16,
{ "Float 16 Bit", "cbor.type.float16",
FT_FLOAT, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_float32,
{ "Float 32 Bit", "cbor.type.float32",
FT_FLOAT, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
{ &hf_cbor_type_float64,
{ "Float 64 Bit", "cbor.type.float64",
FT_DOUBLE, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
};
static gint *ett[] = {
&ett_cbor,
&ett_cbor_byte_string_undef,
&ett_cbor_text_string_undef,
&ett_cbor_array,
&ett_cbor_map,
&ett_cbor_map_entry,
&ett_cbor_tag,
};
static ei_register_info ei[] = {
{ &ei_cbor_invalid_minor_type,
{ "cbor.invalid_minor_type", PI_MALFORMED, PI_WARN, "Invalid minor type", EXPFILL }},
{ &ei_cbor_invalid_element,
{ "cbor.invalid_element", PI_MALFORMED, PI_WARN, "Invalid element", EXPFILL }},
{ &ei_cbor_too_long_length,
{ "cbor.too_long_length", PI_MALFORMED, PI_WARN, "Too long length", EXPFILL }},
};
expert_module_t *expert_cbor;
proto_cbor = proto_register_protocol("Concise Binary Object Representation", "CBOR", "cbor");
proto_register_field_array(proto_cbor, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_cbor = expert_register_protocol(proto_cbor);
expert_register_field_array(expert_cbor, ei, array_length(ei));
cbor_handle = register_dissector("cbor", dissect_cbor, proto_cbor);
cborseq_handle = register_dissector("cborseq", dissect_cborseq, proto_cbor);
}
void
proto_reg_handoff_cbor(void)
{
dissector_add_string("media_type", "application/cbor", cbor_handle); /* RFC 7049 */
dissector_add_string("media_type", "application/cbor-seq", cborseq_handle); /* RFC 8742 */
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 8
* tab-width: 8
* indent-tabs-mode: t
* End:
*
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
* :indentSize=8:tabSize=8:noTabs=false:
*/