diff --git a/common/utils/itti_analyzer/libparser/enum_type.c b/common/utils/itti_analyzer/libparser/enum_type.c index 5cc91c0ae0..063872dfa6 100644 --- a/common/utils/itti_analyzer/libparser/enum_type.c +++ b/common/utils/itti_analyzer/libparser/enum_type.c @@ -11,7 +11,7 @@ char *enum_type_get_name_from_value(struct types_s *type, uint32_t value) char *enum_name = "UNKNOWN"; types_t *enum_value; - /* Loop on eache enumeration values */ + /* Loop on each enumeration values */ for (enum_value = type->child; enum_value; enum_value = enum_value->next) { if (value == enum_value->init_value) { enum_name = enum_value->name; @@ -34,6 +34,7 @@ int enum_type_dissect_from_buffer( for (values = type->child; values; values = values->next) { if (value == values->init_value) { + values->parent = type; values->type_dissect_from_buffer( values, ui_set_signal_text_cb, user_data, buffer, offset, parent_offset, type->name == NULL ? indent: indent+4); diff --git a/common/utils/itti_analyzer/libparser/enum_value_type.c b/common/utils/itti_analyzer/libparser/enum_value_type.c index 752d9654dc..bb560ae983 100644 --- a/common/utils/itti_analyzer/libparser/enum_value_type.c +++ b/common/utils/itti_analyzer/libparser/enum_value_type.c @@ -6,10 +6,13 @@ #include "enum_value_type.h" #include "ui_interface.h" +uint32_t last_enum_value; + int enum_value_dissect_from_buffer( struct types_s *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent) { + struct types_s *type_parent = NULL; uint32_t value = 0; DISPLAY_PARSE_INFO("enum_value", type->name, offset, parent_offset); @@ -19,6 +22,24 @@ int enum_value_dissect_from_buffer( int length = 0; char cbuf[50 + strlen(type->name)]; + /* Search for enum variable name and check if it is used in association with a union type */ + { + if (type->parent != NULL) { + /* Ignore ENUMERATION and TYPEDEF parents */ + for (type_parent = type->parent; (type_parent != NULL) && ((type_parent->type == TYPE_ENUMERATION) || (type_parent->type == TYPE_TYPEDEF)); + type_parent = type_parent->parent) { + } + } + if ((type_parent != NULL) && (type_parent->name != NULL) && (strcmp(type_parent->name, "present") == 0)) + { + /* ASN1 union, keep the "present" member */ + last_enum_value = value; + } + else + { + last_enum_value = 0; + } + } sprintf(cbuf, "(0x%08x) %s;\n", value, type->name); length = strlen(cbuf); diff --git a/common/utils/itti_analyzer/libparser/enum_value_type.h b/common/utils/itti_analyzer/libparser/enum_value_type.h index 0bfb7d821b..6db1152482 100644 --- a/common/utils/itti_analyzer/libparser/enum_value_type.h +++ b/common/utils/itti_analyzer/libparser/enum_value_type.h @@ -3,6 +3,8 @@ #ifndef ENUM_VALUE_TYPE_H_ #define ENUM_VALUE_TYPE_H_ +extern uint32_t last_enum_value; + int enum_value_dissect_from_buffer( struct types_s *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent); diff --git a/common/utils/itti_analyzer/libparser/field_type.c b/common/utils/itti_analyzer/libparser/field_type.c index 348c26a5fe..225a75c8a2 100644 --- a/common/utils/itti_analyzer/libparser/field_type.c +++ b/common/utils/itti_analyzer/libparser/field_type.c @@ -24,55 +24,67 @@ int field_dissect_from_buffer( CHECK_FCT(buffer_has_enouch_data(buffer, parent_offset + offset, type->size / 8)); if (type->bits == -1) { - if (type->child != NULL) { - /* Ignore TYPEDEF children */ - for (type_child = type->child; type_child != NULL && type_child->type == TYPE_TYPEDEF; type_child = - type_child->child) { - } - - if (type_child->type == TYPE_ARRAY) { - struct types_s *type_array_child; + if ((type->name != NULL) && (strcmp(type->name, "_asn_ctx") == 0)) { + /* Hide ASN1 asn_struct_ctx_t struct that hold context for parsing across buffer boundaries */ + /* + INDENTED_STRING(cbuf, indent, sprintf(cbuf, ".asn_ctx ...\n")); + length = strlen (cbuf); + ui_set_signal_text_cb(user_data, cbuf, length); + */ + } + else { + if (type->child != NULL) { /* Ignore TYPEDEF children */ - for (type_array_child = type_child->child; - type_array_child != NULL && type_array_child->type == TYPE_TYPEDEF; type_array_child = - type_array_child->child) { + for (type_child = type->child; type_child != NULL && type_child->type == TYPE_TYPEDEF; type_child = + type_child->child) { } - sprintf (array_info, "[%d]", type_child->size / type_array_child->size); + if (type_child->type == TYPE_ARRAY) { + struct types_s *type_array_child; + + /* Ignore TYPEDEF children */ + for (type_array_child = type_child->child; + type_array_child != NULL && type_array_child->type == TYPE_TYPEDEF; type_array_child = + type_array_child->child) { + } + + sprintf (array_info, "[%d]", type_child->size / type_array_child->size); + } + else { + array_info[0] = '\0'; + } + + DISPLAY_TYPE("Fld"); + INDENTED_STRING(cbuf, indent, sprintf(cbuf, ".%s%s = ", type->name ? type->name : "Field", array_info)); + length = strlen (cbuf); + + ui_set_signal_text_cb(user_data, cbuf, length); + + indent_child = indent; + if (type_child->type == TYPE_ARRAY || type_child->type == TYPE_STRUCT || type_child->type == TYPE_UNION) { + DISPLAY_BRACE(ui_set_signal_text_cb(user_data, "{", 1);) + ui_set_signal_text_cb(user_data, "\n", 1); + indent_child += 4; + } + if (type_child->type == TYPE_FUNDAMENTAL || type_child->type == TYPE_POINTER) { + indent_child = 0; + } + + type->child->parent = type; + CHECK_FCT(type->child->type_dissect_from_buffer( + type->child, ui_set_signal_text_cb, user_data, buffer, + parent_offset, offset + type->offset, indent_child)); + + DISPLAY_BRACE( + if (type_child->type == TYPE_ARRAY || type_child->type == TYPE_STRUCT || type_child->type == TYPE_UNION) { + DISPLAY_TYPE("Fld"); + INDENTED_STRING(cbuf, indent, sprintf(cbuf, "};\n")); + length = strlen (cbuf); + + ui_set_signal_text_cb(user_data, cbuf, length); + }); } - else { - array_info[0] = '\0'; - } - - DISPLAY_TYPE("Fld"); - INDENTED_STRING(cbuf, indent, sprintf(cbuf, ".%s%s = ", type->name ? type->name : "Field", array_info)); - length = strlen (cbuf); - - ui_set_signal_text_cb(user_data, cbuf, length); - - indent_child = indent; - if (type_child->type == TYPE_ARRAY || type_child->type == TYPE_STRUCT || type_child->type == TYPE_UNION) { - DISPLAY_BRACE(ui_set_signal_text_cb(user_data, "{", 1);) - ui_set_signal_text_cb(user_data, "\n", 1); - indent_child += 4; - } - if (type_child->type == TYPE_FUNDAMENTAL || type_child->type == TYPE_POINTER) { - indent_child = 0; - } - - CHECK_FCT(type->child->type_dissect_from_buffer( - type->child, ui_set_signal_text_cb, user_data, buffer, - parent_offset, offset + type->offset, indent_child)); - - DISPLAY_BRACE( - if (type_child->type == TYPE_ARRAY || type_child->type == TYPE_STRUCT || type_child->type == TYPE_UNION) { - DISPLAY_TYPE("Fld"); - INDENTED_STRING(cbuf, indent, sprintf(cbuf, "};\n")); - length = strlen (cbuf); - - ui_set_signal_text_cb(user_data, cbuf, length); - }); } } else { diff --git a/common/utils/itti_analyzer/libparser/typedef_type.c b/common/utils/itti_analyzer/libparser/typedef_type.c index ce5f0f9313..193e7449fb 100644 --- a/common/utils/itti_analyzer/libparser/typedef_type.c +++ b/common/utils/itti_analyzer/libparser/typedef_type.c @@ -14,6 +14,7 @@ int typedef_dissect_from_buffer( /* Simply call next_type */ if (type->child != NULL) { + type->child->parent = type; type->child->type_dissect_from_buffer( type->child, ui_set_signal_text_cb, user_data, buffer, offset, parent_offset, indent); } diff --git a/common/utils/itti_analyzer/libparser/union_type.c b/common/utils/itti_analyzer/libparser/union_type.c index 6976bf1bed..a37db03ad0 100644 --- a/common/utils/itti_analyzer/libparser/union_type.c +++ b/common/utils/itti_analyzer/libparser/union_type.c @@ -5,6 +5,7 @@ #include "rc.h" +#include "enum_value_type.h" #include "union_type.h" #include "../libresolver/locate_root.h" #include "ui_interface.h" @@ -34,6 +35,7 @@ int union_dissect_from_buffer( { int length = 0; char cbuf[200]; + int union_child = 0; DISPLAY_PARSE_INFO("union", type->name, offset, parent_offset); @@ -45,6 +47,21 @@ int union_dissect_from_buffer( // INDENTED(stdout, indent, fprintf(stdout, "<%s>\n", type->name)); DISPLAY_TYPE("Uni"); INDENTED_STRING(cbuf, indent, sprintf(cbuf, "%s {\n", type->name)); + + if (type->parent != NULL) + { + if ((type->parent->name != NULL) && (strcmp(type->parent->name, "choice") == 0)) + { + /* ASN1 union */ + + if ((last_enum_value > 0) && (last_enum_value <= type->nb_members)) + { + union_child = last_enum_value - 1; + + g_debug("ASN1 union \"%s\' detected, use member %d", type->name, union_child); + } + } + } } length = strlen (cbuf); @@ -52,9 +69,9 @@ int union_dissect_from_buffer( ui_set_signal_text_cb(user_data, cbuf, length); /* Only dissect the first field present in unions */ - if (type->members_child[0] != NULL) - type->members_child[0]->type_dissect_from_buffer( - type->members_child[0], ui_set_signal_text_cb, user_data, buffer, + if (type->members_child[union_child] != NULL) + type->members_child[union_child]->type_dissect_from_buffer( + type->members_child[union_child], ui_set_signal_text_cb, user_data, buffer, offset, parent_offset, type->name == NULL ? indent : indent + 4); if (type->name) {