summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-yami.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-yami.c')
-rw-r--r--epan/dissectors/packet-yami.c626
1 files changed, 626 insertions, 0 deletions
diff --git a/epan/dissectors/packet-yami.c b/epan/dissectors/packet-yami.c
new file mode 100644
index 00000000..eaa2e757
--- /dev/null
+++ b/epan/dissectors/packet-yami.c
@@ -0,0 +1,626 @@
+/* packet-yami.c
+ * Routines for YAMI dissection
+ * Copyright 2010, Pawel Korbut
+ * Copyright 2012, Jakub Zawadzki <darkjames-ws@darkjames.pl>
+ *
+ * Protocol documentation available at http://www.inspirel.com/yami4/book/B-2.html
+ *
+ * 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 <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/to_str.h>
+#include <wsutil/ws_roundup.h>
+#include "packet-tcp.h"
+
+void proto_reg_handoff_yami(void);
+void proto_register_yami(void);
+
+static gboolean yami_desegment = TRUE;
+
+static dissector_handle_t yami_handle;
+
+#define YAMI_TYPE_BOOLEAN 1
+#define YAMI_TYPE_INTEGER 2
+#define YAMI_TYPE_LONGLONG 3
+#define YAMI_TYPE_DOUBLE 4
+#define YAMI_TYPE_STRING 5
+#define YAMI_TYPE_BINARY 6
+#define YAMI_TYPE_BOOLEAN_ARRAY 7
+#define YAMI_TYPE_INTEGER_ARRAY 8
+#define YAMI_TYPE_LONGLONG_ARRAY 9
+#define YAMI_TYPE_DOUBLE_ARRAY 10
+#define YAMI_TYPE_STRING_ARRAY 11
+#define YAMI_TYPE_BINARY_ARRAY 12
+#define YAMI_TYPE_NESTED 13
+
+static const value_string yami_param_type_vals[] = {
+ { YAMI_TYPE_BOOLEAN, "boolean" },
+ { YAMI_TYPE_INTEGER, "integer" },
+ { YAMI_TYPE_LONGLONG, "long long" },
+ { YAMI_TYPE_DOUBLE, "double" },
+ { YAMI_TYPE_STRING, "string" },
+ { YAMI_TYPE_BINARY, "binary" },
+ { YAMI_TYPE_BOOLEAN_ARRAY, "boolean array" },
+ { YAMI_TYPE_INTEGER_ARRAY, "integer array" },
+ { YAMI_TYPE_LONGLONG_ARRAY, "long long array" },
+ { YAMI_TYPE_DOUBLE_ARRAY, "double array" },
+ { YAMI_TYPE_STRING_ARRAY, "string array" },
+ { YAMI_TYPE_BINARY_ARRAY, "binary array" },
+ { YAMI_TYPE_NESTED, "nested parameters" },
+ { 0, NULL }
+};
+
+static int proto_yami = -1;
+
+static int hf_yami_frame_number = -1;
+static int hf_yami_frame_payload_size = -1;
+static int hf_yami_items_count = -1;
+static int hf_yami_message_data = -1;
+static int hf_yami_message_hdr = -1;
+static int hf_yami_message_header_size = -1;
+static int hf_yami_message_id = -1;
+static int hf_yami_param = -1;
+static int hf_yami_param_name = -1;
+static int hf_yami_param_type = -1;
+static int hf_yami_param_value_bin = -1;
+static int hf_yami_param_value_bool = -1;
+static int hf_yami_param_value_double = -1;
+static int hf_yami_param_value_int = -1;
+static int hf_yami_param_value_long = -1;
+static int hf_yami_param_value_str = -1;
+static int hf_yami_params_count = -1;
+
+static int ett_yami = -1;
+static int ett_yami_msg_hdr = -1;
+static int ett_yami_msg_data = -1;
+static int ett_yami_param = -1;
+
+static int
+dissect_yami_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_item *par_ti)
+{
+ const int orig_offset = offset;
+
+ proto_tree *yami_param;
+ proto_item *ti;
+
+ char *name;
+ int name_offset;
+ guint32 name_len;
+
+ guint32 type;
+
+ ti = proto_tree_add_item(tree, hf_yami_param, tvb, offset, 0, ENC_NA);
+ yami_param = proto_item_add_subtree(ti, ett_yami_param);
+
+ name_offset = offset;
+ name_len = tvb_get_letohl(tvb, offset);
+ offset += 4;
+
+ name = tvb_get_string_enc(pinfo->pool, tvb, offset, name_len, ENC_ASCII | ENC_NA);
+ proto_item_append_text(ti, ": %s", name);
+ proto_item_append_text(par_ti, "%s, ", name);
+ offset += WS_ROUNDUP_4(name_len);
+ proto_tree_add_string(yami_param, hf_yami_param_name, tvb, name_offset, offset - name_offset, name);
+
+ type = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(yami_param, hf_yami_param_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ switch (type) {
+ case YAMI_TYPE_BOOLEAN:
+ {
+ guint32 val = tvb_get_letohl(tvb, offset);
+ proto_item_append_text(ti, ", Type: boolean, Value: %s", val ? "True" : "False");
+ proto_tree_add_item(yami_param, hf_yami_param_value_bool, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ break;
+ }
+
+ case YAMI_TYPE_INTEGER:
+ {
+ gint32 val = tvb_get_letohl(tvb, offset);
+ proto_item_append_text(ti, ", Type: integer, Value: %d", val);
+ proto_tree_add_item(yami_param, hf_yami_param_value_int, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ break;
+ }
+
+ case YAMI_TYPE_LONGLONG:
+ {
+ gint64 val = tvb_get_letoh64(tvb, offset);
+ proto_item_append_text(ti, ", Type: long, Value: %" PRId64, val);
+ proto_tree_add_item(yami_param, hf_yami_param_value_long, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+ break;
+ }
+
+ case YAMI_TYPE_DOUBLE:
+ {
+ gdouble val = tvb_get_letohieee_double(tvb, offset);
+ proto_item_append_text(ti, ", Type: double, Value: %g", val);
+ proto_tree_add_item(yami_param, hf_yami_param_value_double, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+ break;
+ }
+
+ case YAMI_TYPE_STRING:
+ {
+ const int val_offset = offset;
+ guint32 val_len;
+ char *val;
+
+ val_len = tvb_get_letohl(tvb, offset);
+ offset += 4;
+
+ val = tvb_get_string_enc(pinfo->pool, tvb, offset, val_len, ENC_ASCII | ENC_NA);
+
+ proto_item_append_text(ti, ", Type: string, Value: \"%s\"", val);
+ offset += WS_ROUNDUP_4(val_len);
+ proto_tree_add_string(yami_param, hf_yami_param_value_str, tvb, val_offset, offset - val_offset, val);
+ break;
+ }
+
+ case YAMI_TYPE_BINARY:
+ {
+ const int val_offset = offset;
+ guint32 val_len;
+ const guint8 *val;
+ char *repr;
+
+ val_len = tvb_get_letohl(tvb, offset);
+ offset += 4;
+
+ val = tvb_get_ptr(tvb, offset, val_len);
+ repr = bytes_to_str(pinfo->pool, val, val_len);
+
+ proto_item_append_text(ti, ", Type: binary, Value: %s", repr);
+ offset += WS_ROUNDUP_4(val_len);
+ proto_tree_add_bytes_format_value(yami_param, hf_yami_param_value_bin, tvb, val_offset, offset - val_offset, val, "%s", repr);
+ break;
+ }
+
+ case YAMI_TYPE_BOOLEAN_ARRAY:
+ {
+ guint32 count;
+ guint i;
+ int j;
+
+ count = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_item_append_text(ti, ", Type: boolean[], %u items: {", count);
+
+ for (i = 0; i < count/32; i++) {
+ guint32 val = tvb_get_letohl(tvb, offset);
+
+ for (j = 0; j < 32; j++) {
+ int r = !!(val & (1U << j));
+
+ proto_item_append_text(ti, "%s, ", r ? "T" : "F");
+ proto_tree_add_boolean(yami_param, hf_yami_param_value_bool, tvb, offset+(j/8), 1, r);
+ }
+ offset += 4;
+ }
+
+ if (count % 32) {
+ guint32 val = tvb_get_letohl(tvb, offset);
+ int tmp = count % 32;
+
+ for (j = 0; j < tmp; j++) {
+ int r = !!(val & (1 << j));
+
+ proto_item_append_text(ti, "%s, ", r ? "T" : "F");
+ proto_tree_add_boolean(yami_param, hf_yami_param_value_bool, tvb, offset+(j/8), 1, r);
+ }
+ offset += 4;
+ }
+
+ proto_item_append_text(ti, "}");
+ break;
+ }
+
+ case YAMI_TYPE_INTEGER_ARRAY:
+ {
+ guint32 count;
+ guint i;
+
+ count = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_item_append_text(ti, ", Type: integer[], %u items: {", count);
+ for (i = 0; i < count; i++) {
+ gint32 val = tvb_get_letohl(tvb, offset);
+
+ proto_item_append_text(ti, "%d, ", val);
+ proto_tree_add_item(yami_param, hf_yami_param_value_int, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ }
+ proto_item_append_text(ti, "}");
+ break;
+ }
+
+ case YAMI_TYPE_LONGLONG_ARRAY:
+ {
+ guint32 count;
+ guint i;
+
+ count = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_item_append_text(ti, ", Type: long long[], %u items: {", count);
+
+ for (i = 0; i < count; i++) {
+ gint64 val = tvb_get_letoh64(tvb, offset);
+
+ proto_item_append_text(ti, "%" PRId64 ", ", val);
+ proto_tree_add_item(yami_param, hf_yami_param_value_long, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+ }
+ proto_item_append_text(ti, "}");
+ break;
+ }
+
+ case YAMI_TYPE_DOUBLE_ARRAY:
+ {
+ guint32 count;
+ guint i;
+
+ count = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_item_append_text(ti, ", Type: double[], %u items: {", count);
+
+ for (i = 0; i < count; i++) {
+ gdouble val = tvb_get_letohieee_double(tvb, offset);
+
+ proto_item_append_text(ti, "%g, ", val);
+ proto_tree_add_item(yami_param, hf_yami_param_value_double, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+ }
+ proto_item_append_text(ti, "}");
+ break;
+ }
+
+ case YAMI_TYPE_STRING_ARRAY:
+ {
+ guint32 count;
+ guint i;
+
+ count = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_item_append_text(ti, ", Type: string[], %u items: {", count);
+
+ for (i = 0; i < count; i++) {
+ const int val_offset = offset;
+ guint32 val_len;
+ char *val;
+
+ val_len = tvb_get_letohl(tvb, offset);
+ offset += 4;
+
+ val = tvb_get_string_enc(pinfo->pool, tvb, offset, val_len, ENC_ASCII | ENC_NA);
+
+ proto_item_append_text(ti, "\"%s\", ", val);
+ proto_tree_add_string(yami_param, hf_yami_param_value_str, tvb, val_offset, offset - val_offset, val);
+ offset += WS_ROUNDUP_4(val_len);
+ }
+ proto_item_append_text(ti, "}");
+ break;
+ }
+
+ case YAMI_TYPE_BINARY_ARRAY:
+ {
+ guint32 count;
+ guint i;
+
+ count = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_item_append_text(ti, ", Type: binary[], %u items: {", count);
+
+ for (i = 0; i < count; i++) {
+ const int val_offset = offset;
+ guint32 val_len;
+ const guint8 *val;
+ char *repr;
+
+ val_len = tvb_get_letohl(tvb, offset);
+ offset += 4;
+
+ val = tvb_get_ptr(tvb, offset, val_len);
+ repr = bytes_to_str(pinfo->pool, val, val_len);
+
+ proto_item_append_text(ti, "%s, ", repr);
+ offset += WS_ROUNDUP_4(val_len);
+ proto_tree_add_bytes_format_value(yami_param, hf_yami_param_value_bin, tvb, val_offset, offset - val_offset, val, "%s", repr);
+ }
+ proto_item_append_text(ti, "}");
+ break;
+ }
+
+ case YAMI_TYPE_NESTED:
+ {
+ guint32 count;
+ guint i;
+
+ count = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(yami_param, hf_yami_params_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_item_append_text(ti, ", Type: nested, %u parameters: ", count);
+
+ for (i = 0; i < count; i++) {
+ offset = dissect_yami_parameter(tvb, pinfo, yami_param, offset, ti);
+ /* smth went wrong */
+ if (offset == -1)
+ return -1;
+ }
+ break;
+ }
+
+ default:
+ proto_item_append_text(ti, ", Type: unknown (%d)!", type);
+ return -1;
+ }
+
+ proto_item_set_len(ti, offset - orig_offset);
+ return offset;
+}
+
+static int
+dissect_yami_data(tvbuff_t *tvb, packet_info *pinfo, gboolean data, proto_tree *tree, int offset)
+{
+ const int orig_offset = offset;
+
+ proto_tree *yami_data_tree;
+ proto_item *ti;
+
+ guint32 count;
+ guint i;
+
+ ti = proto_tree_add_item(tree, (data) ? hf_yami_message_data : hf_yami_message_hdr, tvb, offset, 0, ENC_NA);
+ yami_data_tree = proto_item_add_subtree(ti, (data) ? ett_yami_msg_data : ett_yami_msg_hdr);
+
+ count = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(yami_data_tree, hf_yami_params_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_item_append_text(ti, ", %u parameters: ", count);
+
+ for (i = 0; i < count; i++) {
+ offset = dissect_yami_parameter(tvb, pinfo, yami_data_tree, offset, ti);
+ /* smth went wrong */
+ if (offset == -1)
+ return -1;
+ }
+
+ proto_item_set_len(ti, offset - orig_offset);
+
+ return offset;
+}
+
+static int
+dissect_yami_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *yami_tree;
+ proto_item *ti;
+
+ gint frame_number;
+ gint message_header_size;
+ gint frame_payload_size;
+ gint frame_size;
+ int offset;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "YAMI");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ ti = proto_tree_add_item(tree, proto_yami, tvb, 0, -1, ENC_NA);
+ yami_tree = proto_item_add_subtree(ti, ett_yami);
+
+ offset = 0;
+
+ proto_tree_add_item(yami_tree, hf_yami_message_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ frame_number = tvb_get_letohl(tvb, offset);
+ ti = proto_tree_add_item(yami_tree, hf_yami_frame_number, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ if(frame_number < 0)
+ proto_item_append_text(ti, "%s", " (last frame)");
+ offset += 4;
+
+ message_header_size = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(yami_tree, hf_yami_message_header_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ if (message_header_size < 4) {
+ /* XXX, expert info */
+ }
+ offset += 4;
+
+ frame_payload_size = tvb_get_letohl(tvb, offset);
+ ti = proto_tree_add_item(yami_tree, hf_yami_frame_payload_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ frame_size = frame_payload_size + 16;
+ proto_item_append_text(ti, ", (YAMI Frame Size: %d)", frame_size);
+ offset += 4;
+
+ if (frame_number == 1 || frame_number == -1) {
+ if (message_header_size <= frame_payload_size) {
+ const int orig_offset = offset;
+
+ offset = dissect_yami_data(tvb, pinfo, FALSE, yami_tree, offset);
+ if (offset != orig_offset + message_header_size) {
+ /* XXX, expert info */
+ offset = orig_offset + message_header_size;
+ }
+
+ dissect_yami_data(tvb, pinfo, TRUE, yami_tree, offset);
+ }
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+#define FRAME_HEADER_LEN 16
+
+static guint
+get_yami_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
+ int offset, void *data _U_)
+{
+ guint32 len = tvb_get_letohl(tvb, offset + 12);
+
+ return len + FRAME_HEADER_LEN;
+}
+
+static int
+dissect_yami(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, yami_desegment, FRAME_HEADER_LEN, get_yami_message_len, dissect_yami_pdu, data);
+ return tvb_captured_length(tvb);
+}
+
+void
+proto_register_yami(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_yami_message_id,
+ { "Message ID", "yami.message_id",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_yami_frame_number,
+ { "Frame Number", "yami.frame_number",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_yami_message_header_size,
+ { "Message Header Size", "yami.message_header_size",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_yami_frame_payload_size,
+ { "Frame Payload Size", "yami.frame_payload_size",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_yami_message_hdr,
+ { "Header message", "yami.msg_hdr",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_yami_message_data,
+ { "Data message", "yami.msg_data",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_yami_param,
+ { "Parameter", "yami.param",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_yami_param_name,
+ { "Name", "yami.param.name",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Parameter name", HFILL }
+ },
+ { &hf_yami_param_type,
+ { "Type", "yami.param.type",
+ FT_INT32, BASE_DEC, VALS(yami_param_type_vals), 0x00,
+ "Parameter type", HFILL }
+ },
+ { &hf_yami_param_value_bool,
+ { "Value", "yami.param.value_bool",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x00,
+ "Parameter value (bool)", HFILL }
+ },
+ { &hf_yami_param_value_int,
+ { "Value", "yami.param.value_int",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ "Parameter value (int)", HFILL }
+ },
+ { &hf_yami_param_value_long,
+ { "Value", "yami.param.value_long",
+ FT_INT64, BASE_DEC, NULL, 0x00,
+ "Parameter value (long)", HFILL }
+ },
+ { &hf_yami_param_value_double,
+ { "Value", "yami.param.value_double",
+ FT_DOUBLE, BASE_NONE, NULL, 0x00,
+ "Parameter value (double)", HFILL }
+ },
+ { &hf_yami_param_value_str,
+ { "Value", "yami.param.value_str",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Parameter value (string)", HFILL }
+ },
+ { &hf_yami_param_value_bin,
+ { "Value", "yami.param.value_bin",
+ FT_BYTES, BASE_NONE, NULL, 0x00,
+ "Parameter value (binary)", HFILL }
+ },
+ { &hf_yami_params_count,
+ { "Parameters count", "yami.params_count",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_yami_items_count,
+ { "Items count", "yami.items_count",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_yami,
+ &ett_yami_msg_hdr,
+ &ett_yami_msg_data,
+ &ett_yami_param
+ };
+
+ module_t *yami_module;
+
+ proto_yami = proto_register_protocol("YAMI Protocol", "YAMI", "yami");
+
+ proto_register_field_array(proto_yami, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ yami_module = prefs_register_protocol(proto_yami, NULL);
+ prefs_register_bool_preference(yami_module, "desegment",
+ "Reassemble YAMI messages spanning multiple TCP segments",
+ "Whether the YAMI dissector should reassemble messages spanning multiple TCP segments."
+ "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
+ &yami_desegment);
+
+ yami_handle = register_dissector("yami", dissect_yami, proto_yami);
+}
+
+void
+proto_reg_handoff_yami(void)
+{
+ dissector_add_for_decode_as_with_preference("tcp.port", yami_handle);
+ dissector_add_for_decode_as_with_preference("udp.port", yami_handle);
+}
+
+/*
+ * 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:
+ */