From 77d94aea243c3eca2be4749fce3145218fdf8b29 Mon Sep 17 00:00:00 2001 From: Juanjo Martin Date: Fri, 29 May 2020 16:54:15 +0200 Subject: RTPS: Added dissection of user data using discovery traffic Change-Id: I5b91416f4135f61d55289e869f00be6ccadc78b6 Reviewed-on: https://code.wireshark.org/review/37335 Petri-Dish: Anders Broman Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- epan/dissectors/packet-rtps-utils.c | 435 ++++++++++++++++++++++++++ epan/dissectors/packet-rtps.c | 591 ++++++++++++++++++++++++++---------- epan/dissectors/packet-rtps.h | 85 +++++- 3 files changed, 946 insertions(+), 165 deletions(-) create mode 100644 epan/dissectors/packet-rtps-utils.c diff --git a/epan/dissectors/packet-rtps-utils.c b/epan/dissectors/packet-rtps-utils.c new file mode 100644 index 0000000000..c785a2686f --- /dev/null +++ b/epan/dissectors/packet-rtps-utils.c @@ -0,0 +1,435 @@ +/* packet-rtps-utils.c + * ~~~~~~~~~~~~~ + * + * The following file contains helper routines for the RTPS packet dissector + * + * (c) 2005-2020 Copyright, Real-Time Innovations, Inc. + * Real-Time Innovations, Inc. + * 232 East Java Drive + * Sunnyvale, CA 94089 + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * ------------------------------------- + * + * The following file is part of the RTPS packet dissector for Wireshark. + * + * RTPS protocol was developed by Real-Time Innovations, Inc. as wire + * protocol for Data Distribution System. + * Additional information at: + * + * OMG DDS standards: http://portals.omg.org/dds/omg-dds-standard/ + * + * Older OMG DDS specification: + * http://www.omg.org/cgi-bin/doc?ptc/2003-07-07 + * + * NDDS and RTPS information: http://www.rti.com/resources.html + * + */ + +#include "config.h" + +#include +#include "packet-rtps.h" + +static wmem_map_t * dissection_infos = NULL; +static wmem_map_t * union_member_mappings = NULL; +static wmem_map_t * mutable_member_mappings = NULL; + +#define DISSECTION_INFO_MAX_ELEMENTS (100) +#define MAX_MEMBER_NAME (256) +#define HASHMAP_DISCRIMINATOR_CONSTANT (-2) + +typedef struct _union_member_mapping { + guint64 union_type_id; + guint64 member_type_id; + gint32 discriminator; + gchar member_name[MAX_MEMBER_NAME]; +} union_member_mapping; + +typedef struct _mutable_member_mapping { + gint64 key; + guint64 struct_type_id; + guint64 member_type_id; + guint32 member_id; + gchar member_name[MAX_MEMBER_NAME]; +} mutable_member_mapping; + +typedef struct _dissection_element { + guint64 type_id; + guint16 flags; + guint32 member_id; + gchar member_name[MAX_MEMBER_NAME]; +} dissection_element; + +typedef struct _dissection_info { + guint64 type_id; + gint member_kind; + guint64 base_type_id; + guint32 member_length; + gchar member_name[MAX_MEMBER_NAME]; + + RTICdrTypeObjectExtensibility extensibility; + + gint32 bound; + gint32 num_elements; + dissection_element elements[DISSECTION_INFO_MAX_ELEMENTS]; + +} dissection_info; + +gint dissect_user_defined(proto_tree *tree, tvbuff_t * tvb, gint offset, guint encoding, + dissection_info * _info, guint64 type_id, gchar * name, + RTICdrTypeObjectExtensibility extensibility, gint offset_zero, + guint16 flags, guint32 element_member_id); + +gint dissect_mutable_member(proto_tree *tree , tvbuff_t * tvb, gint offset, guint encoding, + dissection_info * info, gboolean * is_end) { + + proto_tree * member; + guint32 member_id, member_length; + mutable_member_mapping * mapping; + gint64 key; + + rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); + if ((member_id & PID_LIST_END) == PID_LIST_END){ + /* If this is the end of the list, don't add a tree. + * If we add more logic here in the future, take into account that + * offset is incremented by 4 */ + offset += 0; + *is_end = TRUE; + return offset; + } + if (member_length == 0){ + return offset; + } + member = proto_tree_add_subtree_format(tree, tvb, offset, member_length, ett_rtps_dissection_tree, + NULL, "ID: %d, Length: %d", member_id, member_length); + + { + if (info->base_type_id > 0) { + key = (info->base_type_id + info->base_type_id * member_id); + mapping = (mutable_member_mapping *) wmem_map_lookup(mutable_member_mappings, &(key)); + if (mapping) { /* the library knows how to dissect this */ + proto_item_append_text(member, "(base found 0x%016" G_GINT64_MODIFIER "x)", key); + dissect_user_defined(tree, tvb, offset, encoding, NULL, mapping->member_type_id, + mapping->member_name, EXTENSIBILITY_INVALID, offset, 0, mapping->member_id); + PROTO_ITEM_SET_HIDDEN(member); + return offset + member_length; + } else + proto_item_append_text(member, "(base not found 0x%016" G_GINT64_MODIFIER "x from 0x%016" G_GINT64_MODIFIER "x)", + key, info->base_type_id); + } + } + + key = (info->type_id + info->type_id * member_id); + mapping = (mutable_member_mapping *) wmem_map_lookup(mutable_member_mappings, &(key)); + if (mapping) { /* the library knows how to dissect this */ + proto_item_append_text(member, "(found 0x%016" G_GINT64_MODIFIER "x)", key); + dissect_user_defined(tree, tvb, offset, encoding, NULL, mapping->member_type_id, + mapping->member_name, EXTENSIBILITY_INVALID, offset, 0, mapping->member_id); + + } else + proto_item_append_text(member, "(not found 0x%016" G_GINT64_MODIFIER "x from 0x%016" G_GINT64_MODIFIER "x)", + key, info->type_id); + PROTO_ITEM_SET_HIDDEN(member); + return offset + member_length; +} + +/* this is a recursive function. _info may or may not be NULL depending on the use iteration */ +gint dissect_user_defined(proto_tree *tree, tvbuff_t * tvb, gint offset, guint encoding, + dissection_info * _info, guint64 type_id, gchar * name, + RTICdrTypeObjectExtensibility extensibility, gint offset_zero, + guint16 flags, guint32 element_member_id) { + + guint64 member_kind; + dissection_info * info = NULL; + guint32 member_id, member_length; + + if (_info) { /* first call enters here */ + info = _info; + member_kind = info->member_kind; + } else { + info = (dissection_info *) wmem_map_lookup(dissection_infos, &(type_id)); + if (info != NULL) { + member_kind = info->member_kind; + } else { + member_kind = type_id; + } + } + if (info && (flags & MEMBER_OPTIONAL) == MEMBER_OPTIONAL) { + gint offset_before = offset; + rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); + offset = offset_before; + if (element_member_id != 0 && member_id != element_member_id) + return offset; + } + if (extensibility == EXTENSIBILITY_MUTABLE) { + rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); + offset_zero = offset; + if ((member_id & PID_LIST_END) == PID_LIST_END){ + /* If this is the end of the list, don't add a tree. + * If we add more logic here in the future, take into account that + * offset is incremented by 4 */ + offset += 0; + return offset; + } + if (member_length == 0){ + return offset; + } + } + //proto_item_append_text(tree, "(Before Switch 0x%016" G_GINT64_MODIFIER "x)", type_id); + + switch (member_kind) { + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_BOOLEAN_TYPE: { + gint length = 1; + ALIGN_ZERO(offset, length, offset_zero); + gint16 value = tvb_get_gint8(tvb, offset); + proto_tree_add_boolean_format(tree, hf_rtps_dissection_boolean, tvb, offset, length, value, + "%s: %d", name, value); + offset += length; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_CHAR_8_TYPE: + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_BYTE_TYPE: { + gint length = 1; + ALIGN_ZERO(offset, length, offset_zero); + gint16 value = tvb_get_gint8(tvb, offset); + proto_tree_add_uint_format(tree, hf_rtps_dissection_byte, tvb, offset, length, value, + "%s: %d", name, value); + offset += length; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_INT_16_TYPE: { + gint length = 2; + ALIGN_ZERO(offset, length, offset_zero); + gint16 value = tvb_get_gint16(tvb, offset, encoding); + proto_tree_add_int_format(tree, hf_rtps_dissection_int16, tvb, offset, length, value, + "%s: %d", name, value); + offset += length; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_UINT_16_TYPE: { + gint length = 2; + ALIGN_ZERO(offset, length, offset_zero); + guint16 value = tvb_get_guint16(tvb, offset, encoding); + proto_tree_add_uint_format(tree, hf_rtps_dissection_uint16, tvb, offset, length, value, + "%s: %u", name, value); + offset += length; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_ENUMERATION_TYPE: + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_INT_32_TYPE: { + gint length = 4; + ALIGN_ZERO(offset, length, offset_zero); + gint value = tvb_get_gint32(tvb, offset, encoding); + proto_tree_add_int_format(tree, hf_rtps_dissection_int32, tvb, offset, length, value, + "%s: %d", name, value); + offset += length; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_UINT_32_TYPE: { + gint length = 4; + ALIGN_ZERO(offset, length, offset_zero); + guint value = tvb_get_guint32(tvb, offset, encoding); + proto_tree_add_uint_format(tree, hf_rtps_dissection_uint32, tvb, offset, length, value, + "%s: %u", name, value); + offset += length; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_INT_64_TYPE: { + gint length = 8; + ALIGN_ZERO(offset, length, offset_zero); + gint64 value = tvb_get_gint64(tvb, offset, encoding); + proto_tree_add_int64_format(tree, hf_rtps_dissection_int64, tvb, offset, length, value, + "%s: %"G_GINT64_MODIFIER"d", name, value); + offset += length; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_UINT_64_TYPE: { + gint length = 8; + ALIGN_ZERO(offset, length, offset_zero); + guint64 value = tvb_get_guint64(tvb, offset, encoding); + proto_tree_add_uint64_format(tree, hf_rtps_dissection_uint64, tvb, offset, length, value, + "%s: %"G_GINT64_MODIFIER"u", name, value); + offset += length; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_FLOAT_32_TYPE: { + gint length = 4; + ALIGN_ZERO(offset, length, offset_zero); + gfloat value = tvb_get_ieee_float(tvb, offset, encoding); + proto_tree_add_float_format(tree, hf_rtps_dissection_float, tvb, offset, length, value, + "%s: %.6f", name, value); + offset += length; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_FLOAT_64_TYPE: { + gint length = 8; + ALIGN_ZERO(offset, length, offset_zero); + gdouble value = tvb_get_ieee_double(tvb, offset, encoding); + proto_tree_add_double_format(tree, hf_rtps_dissection_double, tvb, offset, length, value, + "%s: %.6f", name, value); + offset += length; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_FLOAT_128_TYPE: { + gint length = 16; + ALIGN_ZERO(offset, length, offset_zero); + proto_tree_add_item(tree, hf_rtps_dissection_int128, tvb, offset, length, encoding); + offset += length; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_ARRAY_TYPE: { + gint i; + proto_tree * aux_tree; + gint base_offset = offset; + + aux_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_rtps_dissection_tree, + NULL, name); + for (i = 0; i < info->bound; i++) { + gchar temp_buff[MAX_MEMBER_NAME]; + g_snprintf(temp_buff, MAX_MEMBER_NAME, "%s[%u]", name, i); + offset = dissect_user_defined(aux_tree, tvb, offset, encoding, NULL, + info->base_type_id, temp_buff, EXTENSIBILITY_INVALID, offset_zero, 0, 0); + } + proto_item_set_len(aux_tree, offset - base_offset); + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_SEQUENCE_TYPE: { + guint i; + proto_tree * aux_tree; + gint base_offset = offset; + + gint length = 4; + ALIGN_ZERO(offset, length, offset_zero); + guint seq_size = tvb_get_guint32(tvb, offset, encoding); + aux_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1, ett_rtps_dissection_tree, + NULL, "%s (%u elements)", name, seq_size); + offset += 4; + + for (i = 0; i < seq_size; i++) { + gchar temp_buff[MAX_MEMBER_NAME]; + g_snprintf(temp_buff, MAX_MEMBER_NAME, "%s[%u]", name, i); + if (info->base_type_id > 0) + offset = dissect_user_defined(aux_tree, tvb, offset, encoding, NULL, + info->base_type_id, temp_buff, EXTENSIBILITY_INVALID, offset_zero, 0, 0); + } + proto_item_set_len(aux_tree, offset - base_offset); + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_STRING_TYPE: { + gchar * string_value = NULL; + gint length = 4; + ALIGN_ZERO(offset, length, offset_zero); + + guint string_size = tvb_get_guint32(tvb, offset, encoding); + offset += 4; + //proto_item_append_text(tree, "(String length: %u)", string_size); + + string_value = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, string_size, ENC_ASCII); + proto_tree_add_string_format(tree, hf_rtps_dissection_string, tvb, offset, string_size, + string_value, "%s: %s", name, string_value); + + offset += string_size; + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_ALIAS_TYPE: { + offset = dissect_user_defined(tree, tvb, offset, encoding, NULL, + info->base_type_id, name, EXTENSIBILITY_INVALID, offset_zero, 0, 0); + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_UNION_TYPE: { + guint64 key = type_id - 1; + union_member_mapping * result = (union_member_mapping *)wmem_map_lookup(union_member_mappings, &(key)); + + if (result != NULL) { + switch (result->member_type_id) { + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_ENUMERATION_TYPE: + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_INT_32_TYPE: { + gint value = tvb_get_gint32(tvb, offset, encoding); + offset += 4; + key = type_id + value; + result = (union_member_mapping *)wmem_map_lookup(union_member_mappings, &(key)); + if (result != NULL) { + proto_item_append_text(tree, " (discriminator = %d, type_id = 0x%016" G_GINT64_MODIFIER "x)", + value, result->member_type_id); + offset = dissect_user_defined(tree, tvb, offset, encoding, NULL, + result->member_type_id, result->member_name, EXTENSIBILITY_INVALID, offset, 0, 0); + } else { + /* the hashmap uses the type_id to index the objects. substracting -2 here to lookup the discriminator + related to the type_id that identifies an union */ + key = type_id + HASHMAP_DISCRIMINATOR_CONSTANT; + result = (union_member_mapping *)wmem_map_lookup(union_member_mappings, &(key)); + if (result != NULL) { + proto_item_append_text(tree, " (discriminator = %d, type_id = 0x%016" G_GINT64_MODIFIER "x)", + value, result->member_type_id); + offset = dissect_user_defined(tree, tvb, offset, encoding, NULL, + result->member_type_id, result->member_name, EXTENSIBILITY_INVALID, offset, 0, 0); + } + } + break; + } + default: + break; + } + } else { + proto_item_append_text(tree, "(NULL 0x%016" G_GINT64_MODIFIER "x)", type_id); + } + break; + } + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_STRUCTURE_TYPE: { + gint i; + proto_tree * aux_tree; + + offset_zero = offset; + aux_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_rtps_dissection_tree, + NULL, name); + + if (info->extensibility == EXTENSIBILITY_MUTABLE) { + gboolean is_end = FALSE; + while(!is_end) + offset = dissect_mutable_member(aux_tree, tvb, offset, encoding, info, &is_end); + } else { + if (info->base_type_id > 0) { + proto_item_append_text(tree, "(BaseId: 0x%016" G_GINT64_MODIFIER "x)", info->base_type_id); + offset = dissect_user_defined(aux_tree, tvb, offset, encoding, NULL, + info->base_type_id, info->member_name, EXTENSIBILITY_INVALID, + offset, 0, 0); + } + + for (i = 0; i < info->num_elements && i < DISSECTION_INFO_MAX_ELEMENTS; i++) { + if (info->elements[i].type_id > 0) + offset = dissect_user_defined(aux_tree, tvb, offset, encoding, NULL, + info->elements[i].type_id, info->elements[i].member_name, info->extensibility, + offset_zero, info->elements[i].flags, info->elements[i].member_id); + } + } + break; + } + default:{ + /* undefined behavior. this should not happen. the following line helps to debug if it happened */ + proto_item_append_text(tree, "(unknown 0x%016" G_GINT64_MODIFIER "x)", member_kind); + break; + } + } + + if (extensibility == EXTENSIBILITY_MUTABLE) { + offset_zero += member_length; + return offset_zero; + } else { + return offset; + } +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ \ No newline at end of file diff --git a/epan/dissectors/packet-rtps.c b/epan/dissectors/packet-rtps.c index 4ae2c6ae97..088e4bc7eb 100644 --- a/epan/dissectors/packet-rtps.c +++ b/epan/dissectors/packet-rtps.c @@ -46,10 +46,10 @@ #include #include #include "packet-rtps.h" +#include "packet-rtps-utils.c" #include #include #include "zlib.h" - void proto_register_rtps(void); void proto_reg_handoff_rtps(void); @@ -348,6 +348,7 @@ static int hf_rtps_type_object_flags = -1; static int hf_rtps_type_object_member_id = -1; static int hf_rtps_type_object_annotation_value_d = -1; static int hf_rtps_type_object_annotation_value_16 = -1; +static int hf_rtps_type_object_union_label = -1; static int hf_rtps_type_object_bound = -1; static int hf_rtps_type_object_enum_constant_name = -1; static int hf_rtps_type_object_enum_constant_value = -1; @@ -364,6 +365,7 @@ static int hf_rtps_pl_cdr_member_id_ext = -1; static int hf_rtps_pl_cdr_member_length_ext = -1; static int hf_rtps_dcps_publication_data_frame_number = -1; + /* Flag bits */ static int hf_rtps_flag_reserved80 = -1; static int hf_rtps_flag_reserved40 = -1; @@ -588,14 +590,6 @@ static expert_field ei_rtps_parameter_not_decoded = EI_INIT; static expert_field ei_rtps_sm_octets_to_next_header_not_zero = EI_INIT; static expert_field pid_type_csonsistency_invalid_size = EI_INIT; -/***************************************************************************/ -/* Preferences */ -/***************************************************************************/ -static guint rtps_max_batch_samples_dissected = 16; -static gboolean enable_topic_info = FALSE; -static gboolean enable_rtps_reassembly = FALSE; -static dissector_table_t rtps_type_name_table; - /***************************************************************************/ /* Value-to-String Tables */ static const value_string vendor_vals[] = { @@ -1153,34 +1147,6 @@ static const value_string acknowledgement_kind_vals[] = { { 0, NULL } }; -static const value_string type_object_kind [] = { - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_NO_TYPE, "NO_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_BOOLEAN_TYPE, "BOOLEAN_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_BYTE_TYPE, "BYTE_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_INT_16_TYPE, "INT_16_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_UINT_16_TYPE, "UINT_16_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_INT_32_TYPE, "INT_32_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_UINT_32_TYPE, "UINT_32_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_INT_64_TYPE, "INT_64_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_UINT_64_TYPE, "UINT_64_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_FLOAT_32_TYPE, "FLOAT_32_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_FLOAT_64_TYPE, "FLOAT_64_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_FLOAT_128_TYPE, "FLOAT_128_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_CHAR_8_TYPE, "CHAR_8_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_CHAR_32_TYPE, "CHAR_32_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_ENUMERATION_TYPE, "ENUMERATION_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_BITSET_TYPE, "BITSET_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_ALIAS_TYPE, "ALIAS_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_ARRAY_TYPE, "ARRAY_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_SEQUENCE_TYPE, "SEQUENCE_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_STRING_TYPE, "STRING_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_MAP_TYPE, "MAP_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_UNION_TYPE, "UNION_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_STRUCTURE_TYPE, "STRUCTURE_TYPE" }, - { RTI_CDR_TYPE_OBJECT_TYPE_KIND_ANNOTATION_TYPE, "ANNOTATION_TYPE" }, - { 0, NULL } -}; - static const int* TYPE_FLAG_FLAGS[] = { &hf_rtps_flag_typeflag_nested, /* Bit 2 */ &hf_rtps_flag_typeflag_mutable, /* Bit 1 */ @@ -1698,6 +1664,7 @@ typedef struct _type_mapping { gint fields_visited; datawriter_qos dw_qos; guint32 dcps_publication_frame_number; + guint64 type_id; } type_mapping; /* Links a coherent set with an specific writer. Useful to detect if an empty packet is the end of a coherent set */ @@ -2890,19 +2857,6 @@ gint rtps_util_add_seq_ulong(proto_tree *tree, tvbuff_t *tvb, gint offset, int h } -#define LONG_ALIGN(x) (x = (x+3)&0xfffffffc) -#define SHORT_ALIGN(x) (x = (x+1)&0xfffffffe) -#define MAX_ARRAY_DIMENSION 10 -#define ALIGN_ME(offset, alignment) \ - offset = (((offset) + ((alignment) - 1)) & ~((alignment) - 1)) -#define ALIGN_ZERO(offset, alignment, zero) (offset -= zero, ALIGN_ME(offset, alignment), offset += zero) - -#define KEY_COMMENT (" //@key") - -#define LONG_ALIGN_ZERO(x,zero) (x -= zero, LONG_ALIGN(x), x += zero) -#define SHORT_ALIGN_ZERO(x,zero) (x -= zero, SHORT_ALIGN(x), x += zero) - - /* ------------------------------------------------------------------------- */ static const char *rtps_util_typecode_id_to_string(guint32 typecode_id) { switch(typecode_id) { @@ -3532,7 +3486,8 @@ static void rtps_util_dissect_parameter_header(tvbuff_t * tvb, gint * offset, static gint rtps_util_add_type_id(proto_tree *tree, tvbuff_t * tvb, gint offset, const guint encoding, - gint zero, int hf_base, proto_item * append_info_item) { + gint zero, int hf_base, proto_item * append_info_item, + guint64 * type_id) { proto_item * ti; guint16 short_number; guint64 longlong_number; @@ -3556,7 +3511,7 @@ static gint rtps_util_add_type_id(proto_tree *tree, offset += 2; if (short_number <= 13) { - proto_tree_add_item(tree, hf_type, tvb, offset, 2, encoding); + ti = proto_tree_add_item(tree, hf_type, tvb, offset, 2, encoding); if (append_info_item) { proto_item_append_text(append_info_item, "(%s)", val_to_str(short_number, type_object_kind, "(0x%016x)")); @@ -3565,13 +3520,22 @@ static gint rtps_util_add_type_id(proto_tree *tree, } else { ALIGN_ZERO(offset, 8, zero); longlong_number = tvb_get_guint64(tvb, offset, encoding); - proto_tree_add_item(tree, hf_type, tvb, offset, 8, encoding); + ti = proto_tree_add_item(tree, hf_type, tvb, offset, 8, encoding); if (append_info_item) { - proto_item_append_text(append_info_item, "(0x%016" G_GINT64_MODIFIER "x)", longlong_number); + proto_item_append_text(append_info_item, "(0x%016" G_GINT64_MODIFIER "x)", longlong_number); } offset += 8; } + if (short_number <= 13) { + if (type_id) { + *type_id = short_number; + } + } else { + if (type_id) { + *type_id = longlong_number; + } + } return offset; } @@ -3579,7 +3543,7 @@ static gint rtps_util_add_type_annotation_usage(proto_tree *tree, tvbuff_t * tvb, gint offset, const guint encoding, gint zero) { guint32 long_number, i; guint16 short_number; - offset = rtps_util_add_type_id(tree, tvb, offset, encoding, zero, -1, NULL); + offset = rtps_util_add_type_id(tree, tvb, offset, encoding, zero, -1, NULL, NULL); long_number = tvb_get_guint32(tvb, offset, encoding); offset += 4; for (i = 0; i < long_number; i++) { @@ -3601,8 +3565,9 @@ static gint rtps_util_add_type_annotation_usage(proto_tree *tree, } return offset; } + static gint rtps_util_add_type_library_type(proto_tree *tree, - tvbuff_t * tvb, gint offset, const guint encoding) { + tvbuff_t * tvb, gint offset, const guint encoding, dissection_info *info) { proto_tree * annotation_tree; guint32 member_id = 0, member_length = 0, long_number, i; gint offset_tmp; @@ -3615,12 +3580,26 @@ static gint rtps_util_add_type_library_type(proto_tree *tree, short_number = tvb_get_guint16(tvb, offset_tmp, encoding); proto_tree_add_bitmask_value(tree, tvb, offset_tmp, hf_rtps_type_object_flags, ett_rtps_flags, TYPE_FLAG_FLAGS, short_number); + if (info) { + if (short_number & 0x02) + info->extensibility = EXTENSIBILITY_MUTABLE; + else if (short_number & 0x01) + info->extensibility = EXTENSIBILITY_FINAL; + else + info->extensibility = EXTENSIBILITY_EXTENSIBLE; + } offset_tmp += 2; - offset_tmp = rtps_util_add_type_id(tree, tvb, offset_tmp, encoding, offset, -1, tree); + if (info) + offset_tmp = rtps_util_add_type_id(tree, tvb, offset_tmp, encoding, offset, -1, tree, &(info->type_id)); + else + offset_tmp = rtps_util_add_type_id(tree, tvb, offset_tmp, encoding, offset, -1, tree, NULL); rtps_util_add_string(tree, tvb, offset_tmp, hf_rtps_type_object_type_property_name, encoding); long_number = tvb_get_guint32(tvb, offset_tmp, encoding); name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset_tmp+4, long_number, ENC_ASCII); + if (info) + g_strlcpy(info->member_name, name, long_number); + proto_item_append_text(tree, " %s", name); offset += member_length; @@ -3641,13 +3620,15 @@ static gint rtps_util_add_type_library_type(proto_tree *tree, return offset; } + static void rtps_util_add_type_element_enumeration(proto_tree *tree, - tvbuff_t * tvb, gint offset, const guint encoding) { + tvbuff_t * tvb, gint offset, const guint encoding, dissection_info * info) { proto_tree * enumerated_constant; guint32 member_id = 0, member_length = 0; guint32 long_number, i; gint enum_size, offset_tmp = offset; - offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding); + + offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding, info); rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); /* dissect Bound */ @@ -3673,17 +3654,19 @@ static void rtps_util_add_type_element_enumeration(proto_tree *tree, offset_tmp = rtps_util_add_string(enumerated_constant, tvb, offset_tmp, hf_rtps_type_object_enum_constant_name, encoding); proto_item_set_len(enumerated_constant, offset_tmp - enum_size); } + + info->num_elements = 0; } static void rtps_util_add_type_element_sequence(proto_tree *tree, - tvbuff_t * tvb, gint offset, const guint encoding) { + tvbuff_t * tvb, gint offset, const guint encoding, dissection_info * info) { guint32 member_id = 0, member_length = 0; gint zero_alignment; - offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding); + offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding, info); rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); zero_alignment = offset; - rtps_util_add_type_id(tree, tvb, offset, encoding, zero_alignment, -1 , NULL); + rtps_util_add_type_id(tree, tvb, offset, encoding, zero_alignment, -1 , NULL, &(info->base_type_id)); offset += member_length; rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); proto_tree_add_item(tree, hf_rtps_type_object_element_shared, tvb, offset, 1, encoding); @@ -3691,17 +3674,19 @@ static void rtps_util_add_type_element_sequence(proto_tree *tree, rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); /* dissect Bound */ proto_tree_add_item(tree, hf_rtps_type_object_bound, tvb, offset, 4, encoding); + if (info) + info->bound = tvb_get_gint32(tvb, offset, encoding); } static void rtps_util_add_type_element_string(proto_tree *tree, - tvbuff_t * tvb, gint offset, const guint encoding) { + tvbuff_t * tvb, gint offset, const guint encoding, dissection_info * info _U_) { guint32 member_id = 0, member_length = 0; gint zero_alignment; - offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding); + offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding, info); rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); zero_alignment = offset; - rtps_util_add_type_id(tree, tvb, offset, encoding, zero_alignment, -1, NULL); + rtps_util_add_type_id(tree, tvb, offset, encoding, zero_alignment, -1, NULL, NULL); offset += member_length; rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); proto_tree_add_item(tree, hf_rtps_type_object_element_shared, tvb, offset, 1, encoding); @@ -3713,17 +3698,17 @@ static void rtps_util_add_type_element_string(proto_tree *tree, } static void rtps_util_add_type_element_array(proto_tree *tree, - tvbuff_t * tvb, gint offset, const guint encoding) { + tvbuff_t * tvb, gint offset, const guint encoding, dissection_info * info _U_) { proto_tree * bound_tree; guint32 member_id = 0, member_length = 0; guint32 long_number, i; gint zero_alignment, offset_tmp; - offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding); + offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding, info); /* Dissect Collection Type */ rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); zero_alignment = offset; - rtps_util_add_type_id(tree, tvb, offset, encoding, zero_alignment, -1, NULL); + rtps_util_add_type_id(tree, tvb, offset, encoding, zero_alignment, -1, NULL, &(info->base_type_id)); offset += member_length; rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); proto_tree_add_item(tree, hf_rtps_type_object_element_shared, tvb, offset, 1, encoding); @@ -3740,45 +3725,70 @@ static void rtps_util_add_type_element_array(proto_tree *tree, offset_tmp += 4; for (i = 0; i < long_number ; i++) { proto_tree_add_item(bound_tree, hf_rtps_type_object_bound, tvb, offset_tmp, 4, encoding); + if (info) info->bound = tvb_get_gint32(tvb, offset_tmp, encoding); + if (info) info->num_elements = tvb_get_gint32(tvb, offset_tmp, encoding); + offset_tmp += 4; } } static void rtps_util_add_type_element_alias(proto_tree *tree, - tvbuff_t * tvb, gint offset, const guint encoding) { + tvbuff_t * tvb, gint offset, const guint encoding, dissection_info * info) { guint32 member_id = 0, member_length = 0; - offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding); + offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding, info); /* dissect base_type */ rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); - rtps_util_add_type_id(tree, tvb, offset, encoding, offset, hf_rtps_type_object_base_type, NULL); + rtps_util_add_type_id(tree, tvb, offset, encoding, offset, hf_rtps_type_object_base_type, NULL, &(info->base_type_id)); } static gint rtps_util_add_type_member(proto_tree *tree, - tvbuff_t * tvb, gint offset, const guint encoding) { + tvbuff_t * tvb, gint offset, const guint encoding, + dissection_info * info, dissection_element * member_object) { proto_tree * member_property, *annotation_tree; guint32 member_id = 0, member_length = 0; guint32 long_number, i; guint16 short_number; + guint64 member_type_id; gint offset_tmp; gchar * name = NULL; + member_property = proto_tree_add_subtree(tree, tvb, offset, 0, ett_rtps_type_element, NULL, "Member Property"); rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); offset_tmp = offset; short_number = tvb_get_guint16(tvb, offset_tmp, encoding); - proto_tree_add_bitmask_value(tree, tvb, offset_tmp, hf_rtps_type_object_flags, + proto_tree_add_bitmask_value(member_property, tvb, offset_tmp, hf_rtps_type_object_flags, ett_rtps_flags, MEMBER_FLAGS, short_number); + if (member_object) member_object->flags = short_number; offset_tmp += 2; ALIGN_ZERO(offset_tmp, 4, offset); proto_tree_add_item(member_property, hf_rtps_type_object_member_id, tvb, offset_tmp, 4, encoding); member_id = tvb_get_guint32(tvb, offset_tmp, encoding); offset_tmp += 4; offset_tmp = rtps_util_add_type_id(member_property, tvb, offset_tmp, encoding, - offset, -1, tree); + offset, -1, tree, &member_type_id); rtps_util_add_string(member_property, tvb, offset_tmp, hf_rtps_type_object_name, encoding); long_number = tvb_get_guint32(tvb, offset_tmp, encoding); name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset_tmp+4, long_number, ENC_ASCII); proto_item_append_text(tree, " %s (ID: %d)", name, member_id); + if (member_object) { + member_object->member_id = member_id; + g_strlcpy(member_object->member_name, name, long_number < 256 ? long_number : 256); + member_object->type_id = member_type_id; + } + if (info && info->extensibility == EXTENSIBILITY_MUTABLE) { + mutable_member_mapping * mutable_mapping = NULL; + mutable_mapping = wmem_new(wmem_file_scope(), mutable_member_mapping); + g_strlcpy(mutable_mapping->member_name, name, long_number < 256 ? long_number : 256); + mutable_mapping->struct_type_id = info->type_id; + mutable_mapping->member_type_id = member_type_id; + mutable_mapping->member_id = member_id; + mutable_mapping->key = (mutable_mapping->struct_type_id + mutable_mapping->struct_type_id * mutable_mapping->member_id); + proto_item_append_text(tree, "(Inserted 0x%016" G_GINT64_MODIFIER "x from 0x%016" G_GINT64_MODIFIER "x)", mutable_mapping->key, mutable_mapping->struct_type_id); + wmem_map_insert(mutable_member_mappings, &(mutable_mapping->key), (void *) mutable_mapping); + + } + offset += member_length; rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); @@ -3794,40 +3804,162 @@ static gint rtps_util_add_type_member(proto_tree *tree, } offset += member_length; - offset += 4; /* PID_LIST_END */ + long_number = tvb_get_guint32(tvb, offset, encoding); + if ((long_number & PID_LIST_END) == PID_LIST_END) { + offset += 4; + } + + return offset; +} + +static gint rtps_util_add_type_union_member(proto_tree *tree, + tvbuff_t * tvb, gint offset, const guint encoding, guint64 union_type_id, + gboolean is_discriminator, dissection_info * info _U_) { + proto_tree * labels; + gint long_number, i; + gint offset_tmp; + guint32 member_id = 0, member_length = 0; + dissection_element object; + offset = rtps_util_add_type_member(tree, tvb, offset, encoding, NULL, &object); //&(info->elements[i]) + + rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); + offset_tmp = offset; + + long_number = tvb_get_guint32(tvb, offset_tmp, encoding); + + labels = proto_tree_add_subtree_format(tree, tvb, offset_tmp, member_length, + ett_rtps_type_enum_constant, NULL, "Labels (%u elements)", long_number); + offset_tmp += 4; + if ((object.flags & 8) == 8) { + union_member_mapping * mapping = NULL; + + mapping = wmem_new(wmem_file_scope(), union_member_mapping); + g_strlcpy(mapping->member_name, object.member_name, 256); + mapping->member_type_id = object.type_id; + mapping->discriminator = HASHMAP_DISCRIMINATOR_CONSTANT; + mapping->union_type_id = union_type_id + mapping->discriminator; + + wmem_map_insert(union_member_mappings, &(mapping->union_type_id), (void *) mapping); + proto_item_append_text(labels, " Added mapping for discriminator (0x%016" G_GINT64_MODIFIER "x) name = %s", + mapping->union_type_id, mapping->member_name); + } + if (is_discriminator) { + union_member_mapping * mapping = NULL; + + mapping = wmem_new(wmem_file_scope(), union_member_mapping); + g_strlcpy(mapping->member_name, object.member_name, 256); + mapping->member_type_id = object.type_id; + mapping->discriminator = -1; + mapping->union_type_id = union_type_id + mapping->discriminator; + + wmem_map_insert(union_member_mappings, &(mapping->union_type_id), (void *) mapping); + proto_item_append_text(labels, " Added mapping for discriminator (0x%016" G_GINT64_MODIFIER "x) name = %s", + mapping->union_type_id, mapping->member_name); + } + for (i = 0; i < long_number; i++) { + proto_item * ti; + union_member_mapping * mapping = NULL; + guint32 discriminator_case; + + mapping = wmem_new(wmem_file_scope(), union_member_mapping); + + discriminator_case = tvb_get_guint32(tvb, offset_tmp, encoding); + ti = proto_tree_add_item(labels, hf_rtps_type_object_union_label, tvb, offset_tmp, 4, encoding); + offset_tmp += 4; + + g_strlcpy(mapping->member_name, object.member_name, 256); + mapping->member_type_id = object.type_id; + mapping->discriminator = discriminator_case; + mapping->union_type_id = union_type_id + discriminator_case; + + wmem_map_insert(union_member_mappings, &(mapping->union_type_id), (void *) mapping); + proto_item_append_text(ti, " Added mapping for discriminator (0x%016" G_GINT64_MODIFIER "x) name = %s", + mapping->union_type_id, mapping->member_name); + } + + offset += member_length; + long_number = tvb_get_guint32(tvb, offset_tmp, encoding); + + if ((long_number & PID_LIST_END) == PID_LIST_END) { + offset += 4; + } return offset; } + +static void rtps_util_add_type_element_union(proto_tree *tree, + tvbuff_t * tvb, gint offset, const guint encoding, dissection_info * info) { + proto_tree * members; + guint32 member_id = 0, member_length = 0; + guint32 long_number, i; + gint offset_tmp; + offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding, info); + + rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); + offset_tmp = offset; + + long_number = tvb_get_guint32(tvb, offset_tmp, encoding); + members = proto_tree_add_subtree(tree, tvb, offset_tmp, -1, + ett_rtps_type_enum_constant, NULL, "Members"); + + offset_tmp += 4; + + for (i = 0; i < long_number; i++) { + proto_tree * member = NULL; + gint offset_member = offset_tmp; + member = proto_tree_add_subtree(members, tvb, offset_tmp, 0, + ett_rtps_type_enum_constant, NULL, "Member"); + offset_tmp = rtps_util_add_type_union_member(member, tvb, offset_tmp, encoding, + info->type_id, (i == 0), info); + proto_item_set_len(member, offset_tmp - offset_member); + } + + long_number = tvb_get_guint32(tvb, offset_tmp, encoding); + if ((long_number & PID_LIST_END) == PID_LIST_END) { + offset_tmp += 4; + } + proto_item_set_len(members, offset_tmp - offset); +} + static void rtps_util_add_type_element_struct(proto_tree *tree, - tvbuff_t * tvb, gint offset, const guint encoding) { + tvbuff_t * tvb, gint offset, const guint encoding, dissection_info * info) { proto_tree * member; guint32 member_id = 0, member_length = 0; guint32 long_number, i; gint offset_tmp, member_size; - offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding); + + offset = rtps_util_add_type_library_type(tree, tvb, offset, encoding, info); /* dissect base_type */ rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); - offset = rtps_util_add_type_id(tree, tvb, offset, encoding, offset, hf_rtps_type_object_base_type, NULL); + offset = rtps_util_add_type_id(tree, tvb, offset, encoding, offset, hf_rtps_type_object_base_type, NULL, &(info->base_type_id)); rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); /* dissect seq_member*/ + offset_tmp = offset; long_number = tvb_get_guint32(tvb, offset_tmp, encoding); + offset_tmp += 4; for (i = 0; i < long_number; i++) { member_size = offset_tmp; member = proto_tree_add_subtree(tree, tvb, offset_tmp, 0, ett_rtps_type_enum_constant, NULL, ""); - offset_tmp = rtps_util_add_type_member(member, tvb, offset_tmp, encoding); + if (info) + offset_tmp = rtps_util_add_type_member(member, tvb, offset_tmp, encoding, info, &(info->elements[i])); + else + offset_tmp = rtps_util_add_type_member(member, tvb, offset_tmp, encoding, NULL, NULL); proto_item_set_len(member, offset_tmp - member_size); } + if (info) + info->num_elements = long_number; + } static void rtps_util_add_type_library(proto_tree *tree, packet_info * pinfo, tvbuff_t * tvb, gint offset, const guint encoding, guint32 size); static void rtps_util_add_type_element_module(proto_tree *tree, packet_info * pinfo, - tvbuff_t * tvb, gint offset, const guint encoding) { + tvbuff_t * tvb, gint offset, const guint encoding, dissection_info * info _U_) { guint32 long_number; gchar * name = NULL; long_number = tvb_get_guint32(tvb, offset, encoding); @@ -3842,36 +3974,46 @@ static gint rtps_util_add_type_library_element(proto_tree *tree, packet_info * p guint32 long_number; guint32 member_id = 0, member_length = 0; gint initial_offset = offset; + dissection_info * info = NULL; + + info = wmem_new(wmem_file_scope(), dissection_info); + rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); long_number = tvb_get_guint32(tvb, offset, encoding); + info->member_kind = long_number; + element_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_rtps_type_element, NULL, ""); offset += member_length; rtps_util_dissect_parameter_header(tvb, &offset, encoding, &member_id, &member_length); proto_item_set_len(element_tree, member_length + offset - initial_offset); switch (long_number) { - case 14: /*ENUMERATION */ - rtps_util_add_type_element_enumeration(element_tree, tvb, offset, encoding); + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_ENUMERATION_TYPE: /*ENUMERATION */ + rtps_util_add_type_element_enumeration(element_tree, tvb, offset, encoding, info); + break; + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_ALIAS_TYPE: /* ALIAS */ + rtps_util_add_type_element_alias(element_tree, tvb, offset, encoding, info); break; - case 16: /* ALIAS */ - rtps_util_add_type_element_alias(element_tree, tvb, offset, encoding); + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_ARRAY_TYPE: /* ARRAY */ + rtps_util_add_type_element_array(element_tree, tvb, offset, encoding, info); break; - case 17: /* ARRAY */ - rtps_util_add_type_element_array(element_tree, tvb, offset, encoding); + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_SEQUENCE_TYPE: /* SEQUENCE */ + rtps_util_add_type_element_sequence(element_tree, tvb, offset, encoding, info); break; - case 18: /* SEQUENCE */ - rtps_util_add_type_element_sequence(element_tree, tvb, offset, encoding); + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_STRING_TYPE: /* STRING : COLLECTION */ + rtps_util_add_type_element_string(element_tree, tvb, offset, encoding, info); break; - case 19: /* STRING : COLLECTION */ - rtps_util_add_type_element_string(element_tree, tvb, offset, encoding); + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_UNION_TYPE: + rtps_util_add_type_element_union(element_tree, tvb, offset, encoding, info); break; - case 22: /* STRUCT */ - rtps_util_add_type_element_struct(element_tree, tvb, offset, encoding); + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_STRUCTURE_TYPE: /* STRUCT */ + rtps_util_add_type_element_struct(element_tree, tvb, offset, encoding, info); break; - case 24: - rtps_util_add_type_element_module(element_tree, pinfo, tvb, offset, encoding); + case RTI_CDR_TYPE_OBJECT_TYPE_KIND_MODULE: + rtps_util_add_type_element_module(element_tree, pinfo, tvb, offset, encoding, info); break; default: + proto_item_append_text(element_tree, "Kind: %u", long_number); proto_tree_add_item(element_tree, hf_rtps_type_object_element_raw, tvb, offset, member_length, encoding); break; @@ -3885,6 +4027,9 @@ static gint rtps_util_add_type_library_element(proto_tree *tree, packet_info * p } offset += 4; proto_item_set_len(element_tree, offset - initial_offset); + + wmem_map_insert(dissection_infos, &(info->type_id), (void *) info); + return offset; } static void rtps_util_add_type_library(proto_tree *tree, packet_info * pinfo, @@ -3901,11 +4046,14 @@ static void rtps_util_add_type_library(proto_tree *tree, packet_info * pinfo, } } static void rtps_util_add_typeobject(proto_tree *tree, packet_info * pinfo, - tvbuff_t * tvb, gint offset, const guint encoding, guint32 size) { + tvbuff_t * tvb, gint offset, const guint encoding, guint32 size, + type_mapping * type_mapping_object ) { proto_tree * typeobject_tree; gint offset_tmp = 0; guint32 member_id = 0, member_length = 0; guint32 long_number; + guint64 type_id; + typeobject_tree = proto_tree_add_subtree(tree, tvb, offset, size, ett_rtps_type_object, NULL, "Type Object"); /* --- This is the standard parameterized serialization --- */ @@ -3922,7 +4070,8 @@ static void rtps_util_add_typeobject(proto_tree *tree, packet_info * pinfo, offset_tmp = offset; /* Dissect the member. In this case, the typeid is an union with a short * as a discriminator*/ - rtps_util_add_type_id(typeobject_tree, tvb, offset_tmp, encoding, offset, -1, NULL); + rtps_util_add_type_id(typeobject_tree, tvb, offset_tmp, encoding, offset, -1, NULL, &type_id); + if (type_mapping_object) type_mapping_object->type_id = type_id; offset = offset + member_length; /* End _TypeId */ @@ -3936,7 +4085,8 @@ static void rtps_util_add_typeobject(proto_tree *tree, packet_info * pinfo, static void rtps_add_zlib_compressed_typeobject(proto_tree *tree _U_, packet_info * pinfo _U_, - tvbuff_t * tvb _U_, gint offset _U_, const guint encoding _U_, guint compressed_size _U_, guint decompressed_size _U_) { + tvbuff_t * tvb _U_, gint offset _U_, const guint encoding _U_, guint compressed_size _U_, + guint decompressed_size _U_, type_mapping * type_mapping_object) { #ifdef HAVE_ZLIB tvbuff_t *decompressed_data_child_tvb; @@ -3949,7 +4099,7 @@ static void rtps_add_zlib_compressed_typeobject(proto_tree *tree _U_, packet_inf decompressed_type_object_subtree = proto_tree_add_subtree(tree, decompressed_data_child_tvb, 0, 0, ett_rtps_decompressed_type_object, NULL, "[Uncompressed type object]"); rtps_util_add_typeobject(decompressed_type_object_subtree, pinfo, - decompressed_data_child_tvb, 0, encoding, decompressed_size); + decompressed_data_child_tvb, 0, encoding, decompressed_size, type_mapping_object); } else { proto_tree_add_subtree(tree, compressed_type_object_subset, @@ -4252,48 +4402,51 @@ static int rtps_util_add_fragment_number_set(proto_tree *tree, packet_info *pinf proto_item_set_len(ti, offset-original_offset); return offset; } - -static void rtps_util_store_type_mapping(packet_info *pinfo, tvbuff_t *tvb, gint offset, +static void rtps_util_insert_type_mapping_in_registry(packet_info *pinfo, type_mapping *type_mapping_object) { + if (type_mapping_object) { + if ((type_mapping_object->fields_visited & TOPIC_INFO_ALL_SET) == TOPIC_INFO_ALL_SET && + !wmem_map_lookup(registry, &(type_mapping_object->guid))) { + if (((type_mapping_object->guid.entity_id & 0x02) == 0x02) || ((type_mapping_object->guid.entity_id & 0x04) == 0x04)){ + /* If it is an application defined writer matches 0x02. Matches 0x04 if it is an application defined reader */ + type_mapping_object->dcps_publication_frame_number = pinfo->num; + wmem_map_insert(registry, &(type_mapping_object->guid), type_mapping_object); + } + } + } +} +static void rtps_util_store_type_mapping(packet_info *pinfo _U_, tvbuff_t *tvb, gint offset, type_mapping * type_mapping_object, const gchar * value, gint topic_info_add_id) { + if (enable_topic_info && type_mapping_object) { + switch (topic_info_add_id) { + case TOPIC_INFO_ADD_GUID: { + type_mapping_object->guid.host_id = tvb_get_ntohl(tvb, offset); + type_mapping_object->guid.app_id = tvb_get_ntohl(tvb, offset+4); + type_mapping_object->guid.instance_id = tvb_get_ntohl(tvb, offset+8); + type_mapping_object->guid.entity_id = tvb_get_ntohl(tvb, offset+12); + type_mapping_object->fields_visited = + type_mapping_object->fields_visited | TOPIC_INFO_ADD_GUID; + break; + } + case TOPIC_INFO_ADD_TOPIC_NAME: { + g_strlcpy(type_mapping_object->topic_name, value, MAX_TOPIC_AND_TYPE_LENGTH); + type_mapping_object->fields_visited = + type_mapping_object->fields_visited | TOPIC_INFO_ADD_TOPIC_NAME; + break; + } + case TOPIC_INFO_ADD_TYPE_NAME: { + g_strlcpy(type_mapping_object->type_name, value, MAX_TOPIC_AND_TYPE_LENGTH); + type_mapping_object->fields_visited = + type_mapping_object->fields_visited | TOPIC_INFO_ADD_TYPE_NAME; + break; + } - if (enable_topic_info && type_mapping_object) { - switch (topic_info_add_id) { - case TOPIC_INFO_ADD_GUID: { - type_mapping_object->guid.host_id = tvb_get_ntohl(tvb, offset); - type_mapping_object->guid.app_id = tvb_get_ntohl(tvb, offset+4); - type_mapping_object->guid.instance_id = tvb_get_ntohl(tvb, offset+8); - type_mapping_object->guid.entity_id = tvb_get_ntohl(tvb, offset+12); - type_mapping_object->fields_visited = - type_mapping_object->fields_visited | TOPIC_INFO_ADD_GUID; - break; - } - case TOPIC_INFO_ADD_TOPIC_NAME: { - g_strlcpy(type_mapping_object->topic_name, value, MAX_TOPIC_AND_TYPE_LENGTH); - type_mapping_object->fields_visited = - type_mapping_object->fields_visited | TOPIC_INFO_ADD_TOPIC_NAME; - break; - } - case TOPIC_INFO_ADD_TYPE_NAME: { - g_strlcpy(type_mapping_object->type_name, value, MAX_TOPIC_AND_TYPE_LENGTH); - type_mapping_object->fields_visited = - type_mapping_object->fields_visited | TOPIC_INFO_ADD_TYPE_NAME; - break; - } - - default: - break; - } - if ((type_mapping_object->fields_visited & TOPIC_INFO_ALL_SET) == TOPIC_INFO_ALL_SET && - !wmem_map_lookup(registry, &(type_mapping_object->guid))) { - if (((type_mapping_object->guid.entity_id & 0x02) == 0x02) || ((type_mapping_object->guid.entity_id & 0x04) == 0x04)){ - /* If it is an application defined writer matches 0x02. Matches 0x04 if it is an application defined reader */ - type_mapping_object->dcps_publication_frame_number = pinfo->num; - wmem_map_insert(registry, &(type_mapping_object->guid), type_mapping_object); + default: + break; } } - } } + static guint hash_by_guid(gconstpointer key) { const endpoint_guid * guid = (const endpoint_guid *) key; return g_int_hash(&(guid->app_id)); @@ -4305,6 +4458,16 @@ static gboolean compare_by_guid(gconstpointer a, gconstpointer b) { return memcmp(guid_a, guid_b, sizeof(endpoint_guid)) == 0; } +gboolean union_compare(gconstpointer v1, gconstpointer v2) { + const union_member_mapping * a = (const union_member_mapping *) v1; + const union_member_mapping * b = (const union_member_mapping *) v2; + return ((a->union_type_id == b->union_type_id) && (a->discriminator == b->discriminator)); +} + +guint union_hash (gconstpointer v) { + return (guint) *(const guint64*) v; +} + static guint coherent_set_key_hash_by_key(gconstpointer key) { GBytes * coherent_set_object_key_bytes = NULL; coherent_set_object_key_bytes = g_bytes_new(key, sizeof(coherent_set_key)); @@ -4360,7 +4523,7 @@ static void rtps_util_topic_info_add_tree(proto_tree *tree, tvbuff_t *tvb, static gboolean rtps_util_topic_info_add_column_info_and_try_dissector(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint offset, endpoint_guid * guid, - rtps_dissector_data * data) { + rtps_dissector_data * data, guint encoding, gboolean try_dissection_from_type_object) { if (enable_topic_info) { type_mapping * type_mapping_object = rtps_util_get_topic_info(guid); if (type_mapping_object != NULL) { @@ -4372,6 +4535,16 @@ static gboolean rtps_util_topic_info_add_column_info_and_try_dissector(proto_tre col_append_sep_str(pinfo->cinfo, COL_INFO, " -> ", type_mapping_object->topic_name); data->info_displayed = TRUE; } + + if (try_dissection_from_type_object && enable_user_data_dissection) { + dissection_info * info = (dissection_info *) wmem_map_lookup(dissection_infos, &(type_mapping_object->type_id)); + if (info != NULL) { + proto_item_append_text(tree, " (TypeId: 0x%016" G_GINT64_MODIFIER "x)", info->type_id); + return dissect_user_defined(tree, tvb, offset, encoding, info, + info->type_id, info->member_name, EXTENSIBILITY_INVALID, offset, + 0 /* flags */, 0 /* member_id */); + } + } /* This part tries to dissect the content using a dissector */ next_tvb = tvb_new_subset_remaining(tvb, offset); @@ -4574,7 +4747,8 @@ static gint rtps_util_add_rti_service_request(proto_tree * tree, packet_info *pi static gboolean dissect_parameter_sequence_rti_dds(proto_tree *rtps_parameter_tree, packet_info *pinfo, tvbuff_t *tvb, proto_item *parameter_item, proto_item * param_len_item, gint offset, - const guint encoding, int param_length, guint16 parameter, gboolean is_inline_qos, guint vendor_id) { + const guint encoding, int param_length, guint16 parameter, type_mapping * type_mapping_object, + gboolean is_inline_qos, guint vendor_id) { switch(parameter) { @@ -4679,13 +4853,13 @@ static gboolean dissect_parameter_sequence_rti_dds(proto_tree *rtps_parameter_tr proto_tree_add_item(rtps_parameter_tree, hf_rtps_compressed_serialized_type_object, tvb, offset + 12, param_length - 8, encoding); compressed_type_object_subset = tvb_new_subset_length(tvb, offset + 12, decompressed_size); rtps_add_zlib_compressed_typeobject(rtps_parameter_tree, pinfo, compressed_type_object_subset, - 0, encoding, compressed_size, decompressed_size); + 0, encoding, compressed_size, decompressed_size, type_mapping_object); break; } case RTI_OSAPI_COMPRESSION_CLASS_ID_NONE: { compressed_type_object_subset = tvb_new_subset_length(tvb, offset + 12, decompressed_size); rtps_util_add_typeobject(rtps_parameter_tree, pinfo, - compressed_type_object_subset, 0, encoding, decompressed_size); + compressed_type_object_subset, 0, encoding, decompressed_size, type_mapping_object); break; } default: { @@ -5076,7 +5250,7 @@ static gboolean dissect_parameter_sequence_rti_dds(proto_tree *rtps_parameter_tr case PID_TYPE_OBJECT: { rtps_util_add_typeobject(rtps_parameter_tree, pinfo, tvb, - offset, encoding, param_length); + offset, encoding, param_length, type_mapping_object); break; } @@ -6532,7 +6706,6 @@ static gint dissect_parameter_sequence(proto_tree *tree, packet_info *pinfo, tvb proto_tree *rtps_parameter_sequence_tree, *rtps_parameter_tree; guint32 parameter, param_length, param_length_length = 2; gint original_offset = offset, initial_offset = offset; - gboolean dissect_return_value = FALSE; type_mapping * type_mapping_object = NULL; const gchar * param_name = NULL; if (!pinfo->fd->visited) @@ -6655,20 +6828,34 @@ static gint dissect_parameter_sequence(proto_tree *tree, packet_info *pinfo, tvb proto_item_set_len(param_item, param_length+2*param_length_length); /* This way, we can include vendor specific dissections without modifying the main ones */ + + if (!dissect_parameter_sequence_v1(rtps_parameter_tree, pinfo, tvb, param_item, param_len_item, + offset, encoding, size, param_length, parameter, version, type_mapping_object, coherent_set_entity_info_object)) { + if ((version < 0x0200) || + !dissect_parameter_sequence_v2(rtps_parameter_tree, pinfo, tvb, param_item, param_len_item, + offset, encoding, param_length, parameter, + pStatusInfo, vendor_id, type_mapping_object)) { + if (param_length > 0) { + proto_tree_add_item(rtps_parameter_tree, hf_rtps_parameter_data, tvb, + offset, param_length, ENC_NA); + } + } + } + switch (vendor_id) { case RTPS_VENDOR_RTI_DDS: case RTPS_VENDOR_RTI_DDS_MICRO: { - dissect_return_value = dissect_parameter_sequence_rti_dds(rtps_parameter_tree, pinfo, tvb, - param_item, param_len_item, offset, encoding, param_length, parameter, is_inline_qos, vendor_id); + dissect_parameter_sequence_rti_dds(rtps_parameter_tree, pinfo, tvb, + param_item, param_len_item, offset, encoding, param_length, parameter, type_mapping_object, is_inline_qos, vendor_id); break; } case RTPS_VENDOR_TOC: { - dissect_return_value = dissect_parameter_sequence_toc(rtps_parameter_tree, pinfo, tvb, + dissect_parameter_sequence_toc(rtps_parameter_tree, pinfo, tvb, param_item, param_len_item, offset, encoding, param_length, parameter); break; } case RTPS_VENDOR_PT_DDS: { - dissect_return_value = dissect_parameter_sequence_pt(rtps_parameter_tree, pinfo, tvb, + dissect_parameter_sequence_pt(rtps_parameter_tree, pinfo, tvb, param_item, param_len_item, offset, encoding, param_length, parameter); break; } @@ -6676,20 +6863,7 @@ static gint dissect_parameter_sequence(proto_tree *tree, packet_info *pinfo, tvb break; } - if (!dissect_return_value) { - if (!dissect_parameter_sequence_v1(rtps_parameter_tree, pinfo, tvb, param_item, param_len_item, - offset, encoding, size, param_length, parameter, version, type_mapping_object, coherent_set_entity_info_object)) { - if ((version < 0x0200) || - !dissect_parameter_sequence_v2(rtps_parameter_tree, pinfo, tvb, param_item, param_len_item, - offset, encoding, param_length, parameter, - pStatusInfo, vendor_id, type_mapping_object)) { - if (param_length > 0) { - proto_tree_add_item(rtps_parameter_tree, hf_rtps_parameter_data, tvb, - offset, param_length, ENC_NA); - } - } - } - } + rtps_util_insert_type_mapping_in_registry(pinfo, type_mapping_object); offset += param_length; } proto_item_set_len(ti, offset - initial_offset); @@ -6903,6 +7077,7 @@ static void dissect_serialized_data(proto_tree *tree, packet_info *pinfo, tvbuff proto_item *ti; proto_tree *rtps_parameter_sequence_tree; guint16 encapsulation_id; + gboolean try_dissection_from_type_object = FALSE; guint encapsulation_encoding = ENC_BIG_ENDIAN; rtps_dissector_data * data = wmem_new(wmem_packet_scope(), rtps_dissector_data); data->info_displayed = FALSE; @@ -6940,8 +7115,14 @@ static void dissect_serialized_data(proto_tree *tree, packet_info *pinfo, tvbuff /* Add Topic Information if enabled (checked inside). This call attemps to dissect * the sample and will return TRUE if it did. We should return in that case.*/ + if (encapsulation_id == ENCAPSULATION_CDR_LE || + encapsulation_id == ENCAPSULATION_CDR_BE || + encapsulation_id == ENCAPSULATION_PL_CDR_LE || + encapsulation_id == ENCAPSULATION_PL_CDR_BE) { + try_dissection_from_type_object = TRUE; + } if (rtps_util_topic_info_add_column_info_and_try_dissector(rtps_parameter_sequence_tree, - pinfo, tvb, offset, guid, data)) + pinfo, tvb, offset, guid, data, encapsulation_encoding, try_dissection_from_type_object)) return; /* The payload */ @@ -9179,6 +9360,7 @@ static void dissect_RTPS_DATA_BATCH(tvbuff_t *tvb, packet_info *pinfo, gint offs gint32 octectsToSLEncapsulationId; gint32 sampleListOffset; guint32 encapsulation_id; + gboolean try_dissection_from_type_object = FALSE; guint16 *sample_info_flags = NULL; guint32 *sample_info_length = NULL; gint32 sample_info_count = 0, @@ -9376,12 +9558,18 @@ static void dissect_RTPS_DATA_BATCH(tvbuff_t *tvb, packet_info *pinfo, gint offs /* We have enough bytes to dissect the next sample, so we update the rtps_dissector_data * "position in the batch" value and dissect the sample */ data->position_in_batch = count; + if (encapsulation_id == ENCAPSULATION_CDR_LE || + encapsulation_id == ENCAPSULATION_CDR_BE || + encapsulation_id == ENCAPSULATION_PL_CDR_LE || + encapsulation_id == ENCAPSULATION_PL_CDR_BE) { + try_dissection_from_type_object = TRUE; + } if ((sample_info_flags[count] & FLAG_SAMPLE_INFO_K) != 0) { proto_tree_add_bytes_format(sil_tree, hf_rtps_serialized_key, tvb, offset, sample_info_length[count], NULL, "serializedKey[%d]", count); } else { if (!rtps_util_topic_info_add_column_info_and_try_dissector( - sil_tree, pinfo, tvb, offset, guid, data)) { + sil_tree, pinfo, tvb, offset, guid, data, encoding, try_dissection_from_type_object)) { proto_tree_add_bytes_format(sil_tree, hf_rtps_serialized_data, tvb, offset, sample_info_length[count], NULL, "serializedData[%d]", count); } @@ -12344,6 +12532,11 @@ void proto_register_rtps(void) { FT_UINT16, BASE_DEC, 0x0, 0, NULL, HFILL } }, + { &hf_rtps_type_object_union_label, + { "Label", "rtps.type_object.union.label", + FT_UINT32, BASE_DEC, 0x0, 0, + NULL, HFILL } + }, { &hf_rtps_type_object_bound, { "Bound", "rtps.type_object.bound", FT_UINT32, BASE_DEC, 0x0, 0, @@ -12794,6 +12987,66 @@ void proto_register_rtps(void) { { "Compressed serialized type object", "rtps.param.compressed_serialized_typeobject", FT_BYTES, BASE_NONE, NULL, 0x0, "The reassembled payload", HFILL } }, + + { &hf_rtps_dissection_boolean, + {"BOOLEAN", "rtps.dissection.boolean", + FT_BOOLEAN, BASE_DEC, NULL, 0, NULL, HFILL } + }, + + { &hf_rtps_dissection_byte, + {"BYTE", "rtps.dissection.byte", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } + }, + + { &hf_rtps_dissection_int16, + {"INT16", "rtps.dissection.int16", + FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL } + }, + + { &hf_rtps_dissection_uint16, + {"UINT16", "rtps.dissection.uint16", + FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } + }, + + { &hf_rtps_dissection_int32, + {"INT32", "rtps.dissection.int32", + FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL } + }, + + { &hf_rtps_dissection_uint32, + {"UINT32", "rtps.dissection.uint32", + FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } + }, + + { &hf_rtps_dissection_int64, + {"INT64", "rtps.dissection.int64", + FT_INT64, BASE_DEC, NULL, 0, NULL, HFILL } + }, + + { &hf_rtps_dissection_uint64, + {"UINT64", "rtps.dissection.uint64", + FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL } + }, + + { &hf_rtps_dissection_float, + {"FLOAT", "rtps.dissection.float", + FT_FLOAT, BASE_NONE, NULL, 0, NULL, HFILL } + }, + + { &hf_rtps_dissection_double, + {"DOUBLE", "rtps.dissection.double", + FT_DOUBLE, BASE_NONE, NULL, 0, NULL, HFILL } + }, + + { &hf_rtps_dissection_int128, + {"INT128", "rtps.dissection.int128", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } + }, + + { &hf_rtps_dissection_string, + {"STRING", "rtps.dissection.string", + FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL } + }, }; static gint *ett[] = { @@ -12872,7 +13125,8 @@ void proto_register_rtps(void) { &ett_rtps_fragment, &ett_rtps_fragments, &ett_rtps_data_representation, - &ett_rtps_decompressed_type_object + &ett_rtps_decompressed_type_object, + &ett_rtps_dissection_tree }; static ei_register_info ei[] = { @@ -12911,10 +13165,16 @@ void proto_register_rtps(void) { 10, &rtps_max_batch_samples_dissected); prefs_register_bool_preference(rtps_module, "enable_topic_info", - "Enable Topic Information feature", - "Shows the Topic Name and Type Name of the samples.", + "Enable Topic Information", + "Shows the Topic Name and Type Name of the samples. " + "Note: this can considerably increase the dissection time", &enable_topic_info); + prefs_register_bool_preference(rtps_module, "enable_user_data_dissection", + "Enable User Data Dissection (based on Type Object)", + "Dissects the user data if the Type Object is propagated in Discovery.", + &enable_user_data_dissection); + prefs_register_bool_preference(rtps_module, "enable_rtps_reassembly", "Enable RTPS Reassembly", "Enables the reassembly of DATA_FRAG submessages.", @@ -12924,9 +13184,14 @@ void proto_register_rtps(void) { proto_rtps, FT_STRING, BASE_NONE); registry = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), hash_by_guid, compare_by_guid); + dissection_infos = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_int64_hash, g_int64_equal); + union_member_mappings = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_int64_hash, g_int64_equal); + mutable_member_mappings = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_int64_hash, g_int64_equal); coherent_set_tracking.entities_using_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), hash_by_guid, compare_by_guid); coherent_set_tracking.coherent_set_registry_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), coherent_set_key_hash_by_key, compare_by_coherent_set_key); + coherent_set_tracking.entities_using_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), hash_by_guid, compare_by_guid); + /* In order to get this dissector in LUA (aka "chained-dissector") */ register_dissector("rtps", dissect_simple_rtps, proto_rtps); diff --git a/epan/dissectors/packet-rtps.h b/epan/dissectors/packet-rtps.h index 7a3c55b68d..79b03212f0 100644 --- a/epan/dissectors/packet-rtps.h +++ b/epan/dissectors/packet-rtps.h @@ -43,6 +43,17 @@ extern "C" { #endif +#define LONG_ALIGN(x) (x = (x+3)&0xfffffffc) +#define SHORT_ALIGN(x) (x = (x+1)&0xfffffffe) +#define MAX_ARRAY_DIMENSION 10 +#define ALIGN_ME(offset, alignment) \ + offset = (((offset) + ((alignment) - 1)) & ~((alignment) - 1)) +#define ALIGN_ZERO(offset, alignment, zero) (offset -= zero, ALIGN_ME(offset, alignment), offset += zero) + +#define KEY_COMMENT (" //@key") + +#define LONG_ALIGN_ZERO(x,zero) (x -= zero, LONG_ALIGN(x), x += zero) +#define SHORT_ALIGN_ZERO(x,zero) (x -= zero, SHORT_ALIGN(x), x += zero) typedef enum { RTI_CDR_TK_NULL = 0, @@ -95,9 +106,46 @@ typedef enum { RTI_CDR_TYPE_OBJECT_TYPE_KIND_MAP_TYPE=20, RTI_CDR_TYPE_OBJECT_TYPE_KIND_UNION_TYPE=21, RTI_CDR_TYPE_OBJECT_TYPE_KIND_STRUCTURE_TYPE=22, - RTI_CDR_TYPE_OBJECT_TYPE_KIND_ANNOTATION_TYPE=23 + RTI_CDR_TYPE_OBJECT_TYPE_KIND_ANNOTATION_TYPE=23, + RTI_CDR_TYPE_OBJECT_TYPE_KIND_MODULE=24 } RTICdrTypeObjectTypeKind; + +static const value_string type_object_kind [] = { + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_NO_TYPE, "NO_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_BOOLEAN_TYPE, "BOOLEAN_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_BYTE_TYPE, "BYTE_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_INT_16_TYPE, "INT_16_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_UINT_16_TYPE, "UINT_16_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_INT_32_TYPE, "INT_32_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_UINT_32_TYPE, "UINT_32_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_INT_64_TYPE, "INT_64_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_UINT_64_TYPE, "UINT_64_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_FLOAT_32_TYPE, "FLOAT_32_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_FLOAT_64_TYPE, "FLOAT_64_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_FLOAT_128_TYPE, "FLOAT_128_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_CHAR_8_TYPE, "CHAR_8_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_CHAR_32_TYPE, "CHAR_32_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_ENUMERATION_TYPE, "ENUMERATION_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_BITSET_TYPE, "BITSET_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_ALIAS_TYPE, "ALIAS_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_ARRAY_TYPE, "ARRAY_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_SEQUENCE_TYPE, "SEQUENCE_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_STRING_TYPE, "STRING_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_MAP_TYPE, "MAP_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_UNION_TYPE, "UNION_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_STRUCTURE_TYPE, "STRUCTURE_TYPE" }, + { RTI_CDR_TYPE_OBJECT_TYPE_KIND_ANNOTATION_TYPE, "ANNOTATION_TYPE" }, + { 0, NULL } +}; + +typedef enum { + EXTENSIBILITY_INVALID = 1, + EXTENSIBILITY_FINAL, + EXTENSIBILITY_EXTENSIBLE, + EXTENSIBILITY_MUTABLE +} RTICdrTypeObjectExtensibility; + typedef struct _rtps_dissector_data { guint16 encapsulation_id; gboolean info_displayed; @@ -106,7 +154,18 @@ typedef struct _rtps_dissector_data { gint position_in_batch; } rtps_dissector_data; - +/***************************************************************************/ +/* Preferences */ +/***************************************************************************/ +static guint rtps_max_batch_samples_dissected = 16; +static gboolean enable_topic_info = TRUE; +static gboolean enable_rtps_reassembly = FALSE; +static gboolean enable_user_data_dissection = FALSE; +static dissector_table_t rtps_type_name_table; + +/***************************************************************************/ +/* Variable definitions */ +/***************************************************************************/ #define RTPS_MAGIC_NUMBER 0x52545053 /* RTPS */ #define RTPX_MAGIC_NUMBER 0x52545058 /* RTPX */ #define RTPS_SEQUENCENUMBER_UNKNOWN 0xffffffff00000000 /* {-1,0} as uint64 */ @@ -527,6 +586,11 @@ typedef struct _rtps_dissector_data { #define BY_RECEPTION_TIMESTAMP (0) #define BY_SOURCE_TIMESTAMP (1) +/* Member flags */ +#define MEMBER_IS_KEY (1) +#define MEMBER_OPTIONAL (2) +#define MEMBER_SHAREABLE (4) +#define MEMBER_UNION_DEFAULT (8) /* Participant message data kind */ #define PARTICIPANT_MESSAGE_DATA_KIND_UNKNOWN (0x00000000) #define PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE (0x00000001) @@ -576,6 +640,21 @@ typedef struct _rtps_dissector_data { #define RTI_OSAPI_COMPRESSION_CLASS_ID_BZIP2 (2) #define RTI_OSAPI_COMPRESSION_CLASS_ID_AUTO (G_MAXUINT32) +/* These are registered in packet-rtps.c but used in packet-rtps-utils.c */ +static gint ett_rtps_dissection_tree = -1; +static int hf_rtps_dissection_boolean = -1; +static int hf_rtps_dissection_byte = -1; +static int hf_rtps_dissection_int16 = -1; +static int hf_rtps_dissection_uint16 = -1; +static int hf_rtps_dissection_int32 = -1; +static int hf_rtps_dissection_uint32 = -1; +static int hf_rtps_dissection_int64 = -1; +static int hf_rtps_dissection_uint64 = -1; +static int hf_rtps_dissection_float = -1; +static int hf_rtps_dissection_double = -1; +static int hf_rtps_dissection_int128 = -1; +static int hf_rtps_dissection_string = -1; + /* Utilities to add elements to the protocol tree for packet-rtps.h and packet-rtps2.h */ extern guint16 rtps_util_add_protocol_version(proto_tree *tree, tvbuff_t* tvb, gint offset); extern guint16 rtps_util_add_vendor_id(proto_tree *tree, tvbuff_t * tvb, gint offset); @@ -624,6 +703,8 @@ extern void dissect_INFO_SRC(tvbuff_t *tvb, packet_info *pinfo, gint offset, gui const guint encoding, int octets_to_next_header, proto_tree *tree, guint16 rtps_version); extern void dissect_INFO_TS(tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 flags, const guint encoding, int octets_to_next_header, proto_tree *tree); +static void rtps_util_dissect_parameter_header(tvbuff_t * tvb, gint * offset, + const guint encoding, guint32 * member_id, guint32 * member_length); #ifdef __cplusplus -- cgit v1.2.3