summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-erldp.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-erldp.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-erldp.c')
-rw-r--r--epan/dissectors/packet-erldp.c1331
1 files changed, 1331 insertions, 0 deletions
diff --git a/epan/dissectors/packet-erldp.c b/epan/dissectors/packet-erldp.c
new file mode 100644
index 0000000..dcf5052
--- /dev/null
+++ b/epan/dissectors/packet-erldp.c
@@ -0,0 +1,1331 @@
+/* packet-erldp.c
+ * Erlang Distribution Protocol
+ * http://www.erlang.org/doc/apps/erts/erl_dist_protocol.html
+ *
+ * 2010 Tomas Kukosa
+ *
+ * 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/to_str.h>
+#include <epan/reassemble.h>
+#include "packet-tcp.h"
+#include "packet-epmd.h"
+
+#define ERL_PASS_THROUGH 'p'
+
+#define VERSION_MAGIC 131 /* 130 in erlang 4.2 */
+
+#define SMALL_INTEGER_EXT 'a'
+#define INTEGER_EXT 'b'
+#define FLOAT_EXT 'c'
+#define ATOM_EXT 'd'
+#define ATOM_UTF8_EXT 'v'
+#define SMALL_ATOM_EXT 's'
+#define SMALL_ATOM_UTF8_EXT 'w'
+#define REFERENCE_EXT 'e'
+#define NEW_REFERENCE_EXT 'r'
+#define NEWER_REFERENCE_EXT 'Z'
+#define PORT_EXT 'f'
+#define NEW_PORT_EXT 'Y'
+#define NEW_FLOAT_EXT 'F'
+#define PID_EXT 'g'
+#define NEW_PID_EXT 'X'
+#define SMALL_TUPLE_EXT 'h'
+#define LARGE_TUPLE_EXT 'i'
+#define NIL_EXT 'j'
+#define STRING_EXT 'k'
+#define LIST_EXT 'l'
+#define BINARY_EXT 'm'
+#define BIT_BINARY_EXT 'M'
+#define SMALL_BIG_EXT 'n'
+#define LARGE_BIG_EXT 'o'
+#define NEW_FUN_EXT 'p'
+#define EXPORT_EXT 'q'
+#define FUN_EXT 'u'
+
+#define DIST_HEADER 'D'
+#define DIST_FRAG_HEADER 'E'
+#define DIST_FRAG_CONT 'F'
+#define ATOM_CACHE_REF 'R'
+#define COMPRESSED 'P'
+
+#define PNAME "Erlang Distribution Protocol"
+#define PSNAME "ErlDP"
+#define PFNAME "erldp"
+
+void proto_register_erldp(void);
+void proto_reg_handoff_erldp(void);
+
+static const value_string etf_tag_vals[] = {
+ { SMALL_INTEGER_EXT , "SMALL_INTEGER_EXT" },
+ { INTEGER_EXT , "INTEGER_EXT" },
+ { FLOAT_EXT , "FLOAT_EXT" },
+ { ATOM_EXT , "ATOM_EXT" },
+ { ATOM_UTF8_EXT , "ATOM_UTF8_EXT" },
+ { SMALL_ATOM_EXT , "SMALL_ATOM_EXT" },
+ { SMALL_ATOM_UTF8_EXT , "SMALL_ATOM_UTF8_EXT" },
+ { REFERENCE_EXT , "REFERENCE_EXT" },
+ { NEW_REFERENCE_EXT , "NEW_REFERENCE_EXT" },
+ { NEWER_REFERENCE_EXT , "NEWER_REFERENCE_EXT" },
+ { PORT_EXT , "PORT_EXT" },
+ { NEW_PORT_EXT , "NEW_PORT_EXT" },
+ { NEW_FLOAT_EXT , "NEW_FLOAT_EXT" },
+ { PID_EXT , "PID_EXT" },
+ { NEW_PID_EXT , "NEW_PID_EXT" },
+ { SMALL_TUPLE_EXT , "SMALL_TUPLE_EXT" },
+ { LARGE_TUPLE_EXT , "LARGE_TUPLE_EXT" },
+ { NIL_EXT , "NIL_EXT" },
+ { STRING_EXT , "STRING_EXT" },
+ { LIST_EXT , "LIST_EXT" },
+ { BINARY_EXT , "BINARY_EXT" },
+ { BIT_BINARY_EXT , "BIT_BINARY_EXT" },
+ { SMALL_BIG_EXT , "SMALL_BIG_EXT" },
+ { LARGE_BIG_EXT , "LARGE_BIG_EXT" },
+ { NEW_FUN_EXT , "NEW_FUN_EXT" },
+ { EXPORT_EXT , "EXPORT_EXT" },
+ { FUN_EXT , "FUN_EXT" },
+ { DIST_HEADER , "DIST_HEADER" },
+ { DIST_FRAG_HEADER , "DIST_FRAG_HEADER" },
+ { ATOM_CACHE_REF , "ATOM_CACHE_REF" },
+ { COMPRESSED , "COMPRESSED" },
+ { 0, NULL }
+};
+
+static const value_string etf_header_tag_vals[] = {
+ { DIST_HEADER , "DIST_HEADER" },
+ { DIST_FRAG_HEADER , "DIST_FRAG_HEADER" },
+ { DIST_FRAG_CONT , "DIST_FRAG_CONT" },
+ { 0, NULL }
+};
+
+static const value_string erldp_ctlmsg_vals[] = {
+ { 1, "LINK" },
+ { 2, "SEND" },
+ { 3, "EXIT" },
+ { 4, "UNLINK" },
+ { 5, "NODE_LINK" },
+ { 6, "REG_SEND" },
+ { 7, "GROUP_LEADER" },
+ { 8, "EXIT2" },
+ { 12, "SEND_TT" },
+ { 13, "EXIT_TT" },
+ { 16, "REG_SEND_TT" },
+ { 18, "EXIT2_TT" },
+ { 19, "MONITOR_P" },
+ { 20, "DEMONITOR_P" },
+ { 21, "MONITOR_P_EXIT" },
+ { 22, "SEND_SENDER" },
+ { 23, "SEND_SENDER_TT" },
+ { 24, "PAYLOAD_EXIT" },
+ { 25, "PAYLOAD_EXIT_TT" },
+ { 26, "PAYLOAD_EXIT2" },
+ { 27, "PAYLOAD_EXIT2_TT" },
+ { 28, "PAYLOAD_MONITOR_P_EXIT" },
+ { 29, "SPAWN_REQUEST" },
+ { 30, "SPAWN_REQUEST_TT" },
+ { 31, "SPAWN_REPLY" },
+ { 32, "SPAWN_REPLY_TT" },
+ { 0, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_erldp = -1;
+static int hf_erldp_length_2 = -1;
+static int hf_erldp_length_4 = -1;
+static int hf_etf_version_magic = -1;
+static int hf_erldp_tag = -1;
+static int hf_erldp_type = -1;
+static int hf_erldp_version = -1;
+static int hf_erldp_flags_v5 = -1;
+static int hf_erldp_flags_v6 = -1;
+static int hf_erldp_flags_published = -1;
+static int hf_erldp_flags_atom_cache = -1;
+static int hf_erldp_flags_extended_references = -1;
+static int hf_erldp_flags_dist_monitor = -1;
+static int hf_erldp_flags_fun_tags = -1;
+static int hf_erldp_flags_dist_monitor_name = -1;
+static int hf_erldp_flags_hidden_atom_cache = -1;
+static int hf_erldp_flags_new_fun_tags = -1;
+static int hf_erldp_flags_extended_pids_ports = -1;
+static int hf_erldp_flags_export_ptr_tag = -1;
+static int hf_erldp_flags_bit_binaries = -1;
+static int hf_erldp_flags_new_floats = -1;
+static int hf_erldp_flags_unicode_io = -1;
+static int hf_erldp_flags_dist_hdr_atom_cache = -1;
+static int hf_erldp_flags_small_atom_tags = -1;
+static int hf_erldp_flags_ets_compressed = -1;
+static int hf_erldp_flags_utf8_atoms = -1;
+static int hf_erldp_flags_map_tag = -1;
+static int hf_erldp_flags_big_creation = -1;
+static int hf_erldp_flags_send_sender = -1;
+static int hf_erldp_flags_big_seqtrace_labels = -1;
+static int hf_erldp_flags_pending_connect = -1;
+static int hf_erldp_flags_exit_payload = -1;
+static int hf_erldp_flags_fragments = -1;
+static int hf_erldp_flags_handshake_23 = -1;
+static int hf_erldp_flags_unlink_id = -1;
+static int hf_erldp_flags_reserved = -1;
+static int hf_erldp_flags_spawn = -1;
+static int hf_erldp_flags_name_me = -1;
+static int hf_erldp_flags_v4_nc = -1;
+static int hf_erldp_flags_alias = -1;
+static int hf_erldp_flags_spare = -1;
+static int hf_erldp_creation = -1;
+static int hf_erldp_challenge = -1;
+static int hf_erldp_digest = -1;
+static int hf_erldp_nlen = -1;
+static int hf_erldp_name = -1;
+static int hf_erldp_status = -1;
+static int hf_erldp_sequence_id = -1;
+static int hf_erldp_fragment_id = -1;
+static int hf_erldp_num_atom_cache_refs = -1;
+static int hf_erldp_etf_flags = -1;
+static int hf_erldp_internal_segment_index = -1;
+static int hf_erldp_atom_length = -1;
+static int hf_erldp_atom_length2 = -1;
+static int hf_erldp_atom_text = -1;
+static int hf_erldp_atom_cache_ref = -1;
+static int hf_erldp_small_int_ext = -1;
+static int hf_erldp_int_ext = -1;
+static int hf_erldp_small_big_ext_len = -1;
+static int hf_erldp_large_big_ext_len = -1;
+static int hf_erldp_big_ext_int = -1;
+static int hf_erldp_big_ext_str = -1;
+static int hf_erldp_big_ext_bytes = -1;
+static int hf_erldp_float_ext = -1;
+static int hf_erldp_new_float_ext = -1;
+static int hf_erldp_port_ext_id = -1;
+static int hf_erldp_port_ext_creation = -1;
+static int hf_erldp_pid_ext_id = -1;
+static int hf_erldp_pid_ext_serial = -1;
+static int hf_erldp_pid_ext_creation = -1;
+static int hf_erldp_list_ext_len = -1;
+static int hf_erldp_binary_ext_len = -1;
+static int hf_erldp_binary_ext = -1;
+static int hf_erldp_new_ref_ext_len = -1;
+static int hf_erldp_new_ref_ext_creation = -1;
+static int hf_erldp_new_ref_ext_id = -1;
+static int hf_erldp_fun_ext_num_free = -1;
+static int hf_erldp_new_fun_ext_size = -1;
+static int hf_erldp_new_fun_ext_arity = -1;
+static int hf_erldp_new_fun_ext_uniq = -1;
+static int hf_erldp_new_fun_ext_index = -1;
+static int hf_erldp_new_fun_ext_num_free = -1;
+
+static int hf_etf_tag = -1;
+static int hf_etf_dist_header_tag = -1;
+static int hf_etf_dist_header_new_cache = -1;
+static int hf_etf_dist_header_segment_index = -1;
+static int hf_etf_dist_header_long_atoms = -1;
+static int hf_etf_arity4 = -1;
+static int hf_etf_arity = -1;
+
+static int hf_etf_fragments = -1;
+static int hf_etf_fragment = -1;
+static int hf_etf_fragment_overlap = -1;
+static int hf_etf_fragment_overlap_conflicts = -1;
+static int hf_etf_fragment_multiple_tails = -1;
+static int hf_etf_fragment_too_long_fragment = -1;
+static int hf_etf_fragment_error = -1;
+static int hf_etf_fragment_count = -1;
+static int hf_etf_reassembled_in = -1;
+static int hf_etf_reassembled_length = -1;
+static int hf_etf_reassembled_data = -1;
+
+static reassembly_table erldp_reassembly_table;
+
+/* Initialize the subtree pointers */
+static gint ett_erldp = -1;
+static gint ett_erldp_flags = -1;
+
+static gint ett_etf = -1;
+static gint ett_etf_flags = -1;
+static gint ett_etf_acrs = -1;
+static gint ett_etf_acr = -1;
+static gint ett_etf_tmp = -1;
+
+static gint ett_etf_fragment = -1;
+static gint ett_etf_fragments = -1;
+
+/* Preferences */
+static gboolean erldp_desegment = TRUE;
+
+/* Dissectors */
+static dissector_handle_t erldp_handle = NULL;
+
+/* Defragmentation */
+static const fragment_items etf_frag_items = {
+ /* Fragment subtrees */
+ &ett_etf_fragment,
+ &ett_etf_fragments,
+ /* Fragment fields */
+ &hf_etf_fragments,
+ &hf_etf_fragment,
+ &hf_etf_fragment_overlap,
+ &hf_etf_fragment_overlap_conflicts,
+ &hf_etf_fragment_multiple_tails,
+ &hf_etf_fragment_too_long_fragment,
+ &hf_etf_fragment_error,
+ &hf_etf_fragment_count,
+ /* Reassembled in field */
+ &hf_etf_reassembled_in,
+ /* Reassembled length field */
+ &hf_etf_reassembled_length,
+ &hf_etf_reassembled_data,
+ /* Tag */
+ "Message fragments"
+};
+
+/*--- External Term Format ---*/
+
+static gint dissect_etf_type(const gchar *label, packet_info *pinfo, tvbuff_t *tvb, gint offset, proto_tree *tree);
+static gint dissect_etf_pdu_data(packet_info *pinfo, tvbuff_t *tvb, gint offset, proto_tree *tree);
+
+static gint dissect_etf_dist_header(packet_info *pinfo _U_, tvbuff_t *tvb, gint offset, proto_tree *tree) {
+ guint32 num, isi;
+ guint8 flen, i, flg;
+ gint flg_offset, acrs_offset, acr_offset;
+ guint32 atom_txt_len;
+ gboolean new_entry, long_atom;
+ proto_item *ti_acrs, *ti_acr, *ti_tmp;
+ proto_tree *flags_tree, *acrs_tree, *acr_tree;
+ const guint8 *str;
+
+ proto_tree_add_item_ret_uint(tree, hf_erldp_num_atom_cache_refs, tvb, offset, 1, ENC_BIG_ENDIAN, &num);
+ offset++;
+
+ if (num == 0)
+ return offset;
+
+ flg_offset = offset;
+ flen = num / 2 + 1;
+ ti_tmp = proto_tree_add_item(tree, hf_erldp_etf_flags, tvb, offset, flen, ENC_NA );
+ flags_tree = proto_item_add_subtree(ti_tmp, ett_etf_flags);
+ for (i=0; i<num; i++) {
+ flg = tvb_get_guint8(tvb, offset + i / 2);
+ proto_tree_add_boolean_format_value(flags_tree, hf_etf_dist_header_new_cache, tvb, offset + i / 2, 1,
+ (flg & (0x08 << 4*(i%2))), "NewCacheEntryFlag[%2d]: %s",
+ i, (flg & (0x08 << 4*(i%2))) ? "SET" : "---");
+ proto_tree_add_uint_format(flags_tree, hf_etf_dist_header_segment_index, tvb, offset + i / 2, 1,
+ (flg & (0x07 << 4*(i%2))), "SegmentIndex [%2d]: %u",
+ i, (flg & (0x07 << 4*(i%2))));
+ }
+ flg = tvb_get_guint8(tvb, offset + num / 2);
+ proto_tree_add_boolean(flags_tree, hf_etf_dist_header_long_atoms, tvb, offset + num / 2, 1, (flg & (0x01 << 4*(num%2))));
+ long_atom = flg & (0x01 << 4*(num%2));
+ offset += flen;
+
+ acrs_offset = offset;
+ acrs_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_etf_acrs, &ti_acrs, "AtomCacheRefs");
+ for (i=0; i<num; i++) {
+ flg = tvb_get_guint8(tvb, flg_offset + i / 2);
+ new_entry = flg & (0x08 << 4*(i%2));
+ acr_offset = offset;
+ acr_tree = proto_tree_add_subtree_format(acrs_tree, tvb, offset, 0, ett_etf_acr, &ti_acr, "AtomCacheRef[%2d]:", i);
+ proto_tree_add_item_ret_uint(acr_tree, hf_erldp_internal_segment_index, tvb, offset, 1, ENC_BIG_ENDIAN, &isi);
+ proto_item_append_text(ti_acr, " %3d", isi);
+ offset++;
+ if (!new_entry)
+ continue;
+ if (long_atom) {
+ proto_tree_add_item_ret_uint(acr_tree, hf_erldp_atom_length2, tvb, offset, 2, ENC_BIG_ENDIAN, &atom_txt_len);
+ offset += 2;
+ }
+ else {
+ proto_tree_add_item_ret_uint(acr_tree, hf_erldp_atom_length, tvb, offset, 1, ENC_BIG_ENDIAN, &atom_txt_len);
+ offset++;
+ }
+ proto_tree_add_item_ret_string(acr_tree, hf_erldp_atom_text, tvb, offset, atom_txt_len, ENC_NA|ENC_ASCII, wmem_packet_scope(), &str);
+ proto_item_append_text(ti_acr, " - '%s'", str);
+ offset += atom_txt_len;
+ proto_item_set_len(ti_acr, offset - acr_offset);
+ }
+ proto_item_set_len(ti_acrs, offset - acrs_offset);
+
+ return offset;
+}
+
+static gint dissect_etf_tuple_content(gboolean large, packet_info *pinfo, tvbuff_t *tvb, gint offset, proto_tree *tree, const gchar **value_str _U_) {
+ guint32 arity, i;
+
+ if (large) {
+ proto_tree_add_item_ret_uint(tree, hf_etf_arity4, tvb, offset, 4, ENC_BIG_ENDIAN, &arity);
+ offset += 4;
+ } else {
+ proto_tree_add_item_ret_uint(tree, hf_etf_arity, tvb, offset, 1, ENC_BIG_ENDIAN, &arity);
+ offset++;
+ }
+ for (i=0; i<arity; i++) {
+ offset = dissect_etf_type(NULL, pinfo, tvb, offset, tree);
+ }
+
+ return offset;
+}
+
+static gint dissect_etf_big_ext(tvbuff_t *tvb, gint offset, guint32 len, proto_tree *tree, const gchar **value_str) {
+ guint8 sign;
+ gint32 i;
+
+ sign = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ if (len <= 8) {
+ guint64 big_val = 0;
+
+ switch (len) {
+ case 1: big_val = tvb_get_guint8(tvb, offset); break;
+ case 2: big_val = tvb_get_letohs(tvb, offset); break;
+ case 3: big_val = tvb_get_letoh24(tvb, offset); break;
+ case 4: big_val = tvb_get_letohl(tvb, offset); break;
+ case 5: big_val = tvb_get_letoh40(tvb, offset); break;
+ case 6: big_val = tvb_get_letoh48(tvb, offset); break;
+ case 7: big_val = tvb_get_letoh56(tvb, offset); break;
+ case 8: big_val = tvb_get_letoh64(tvb, offset); break;
+ }
+ proto_tree_add_uint64_format_value(tree, hf_erldp_big_ext_int, tvb, offset, len,
+ big_val, "%s%" PRIu64, sign ? "-" : "", big_val);
+ if (value_str)
+ *value_str = wmem_strdup_printf(wmem_packet_scope(), "%s%" PRIu64,
+ sign ? "-" : "", big_val);
+ } if (len < 64) {
+ wmem_strbuf_t *strbuf = wmem_strbuf_new_sized(wmem_packet_scope(), len*1+3+1);
+
+ wmem_strbuf_append(strbuf, "0x");
+ for (i = len - 1; i >= 0; i--) {
+ wmem_strbuf_append_printf(strbuf, "%02x", tvb_get_guint8(tvb, offset + i));
+ }
+ char *buf = wmem_strbuf_finalize(strbuf);
+
+ proto_tree_add_string_format_value(tree, hf_erldp_big_ext_str, tvb, offset, len, buf, "%s", buf);
+
+ if (value_str)
+ *value_str = buf;
+ } else
+ proto_tree_add_item(tree, hf_erldp_big_ext_bytes, tvb, offset, len, ENC_NA);
+
+ return offset + len;
+}
+
+static gint dissect_etf_type_content(guint8 tag, packet_info *pinfo, tvbuff_t *tvb, gint offset, proto_tree *tree, const gchar **value_str) {
+ gint32 int_val;
+ guint32 len, i, uint_val;
+ guint32 id;
+ const guint8 *str_val;
+
+ switch (tag) {
+ case ATOM_CACHE_REF:
+ proto_tree_add_item_ret_uint(tree, hf_erldp_atom_cache_ref, tvb, offset, 1, ENC_BIG_ENDIAN, &uint_val);
+ offset += 1;
+ if (value_str)
+ *value_str = wmem_strdup_printf(wmem_packet_scope(), "%d", uint_val);
+ break;
+
+ case SMALL_INTEGER_EXT:
+ proto_tree_add_item_ret_uint(tree, hf_erldp_small_int_ext, tvb, offset, 1, ENC_BIG_ENDIAN, &uint_val);
+ offset += 1;
+ if (value_str)
+ *value_str = wmem_strdup_printf(wmem_packet_scope(), "%u", uint_val);
+ break;
+
+ case INTEGER_EXT:
+ proto_tree_add_item_ret_int(tree, hf_erldp_int_ext, tvb, offset, 4, ENC_BIG_ENDIAN, &int_val);
+ offset += 4;
+ if (value_str)
+ *value_str = wmem_strdup_printf(wmem_packet_scope(), "%d", int_val);
+ break;
+
+ case SMALL_BIG_EXT: {
+ proto_tree_add_item_ret_uint(tree, hf_erldp_small_big_ext_len, tvb, offset, 1, ENC_BIG_ENDIAN, &len);
+ offset += 1;
+
+ offset = dissect_etf_big_ext(tvb, offset, len, tree, value_str);
+ break;
+ }
+
+ case LARGE_BIG_EXT: {
+ proto_tree_add_item_ret_uint(tree, hf_erldp_large_big_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
+ offset += 4;
+
+ offset = dissect_etf_big_ext(tvb, offset, len, tree, value_str);
+ break;
+ }
+
+ case FLOAT_EXT:
+ proto_tree_add_item_ret_string(tree, hf_erldp_float_ext, tvb, offset, 31, ENC_NA|ENC_UTF_8, wmem_packet_scope(), &str_val);
+ offset += 31;
+ if (value_str)
+ *value_str = (const gchar *)str_val;
+ break;
+
+ case NEW_FLOAT_EXT:
+ proto_tree_add_item(tree, hf_erldp_new_float_ext, tvb, offset, 8, ENC_BIG_ENDIAN);
+ if (value_str) {
+ gdouble new_float_val = tvb_get_ntohieee_double(tvb, offset);
+ *value_str = wmem_strdup_printf(wmem_packet_scope(), "%f", new_float_val);
+ }
+ offset += 8;
+ break;
+
+ case ATOM_UTF8_EXT:
+ proto_tree_add_item_ret_uint(tree, hf_erldp_atom_length2, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
+ offset += 2;
+ proto_tree_add_item_ret_string(tree, hf_erldp_atom_text, tvb, offset, len, ENC_NA|ENC_UTF_8, wmem_packet_scope(), &str_val);
+ offset += len;
+ if (value_str)
+ *value_str = (const gchar *)str_val;
+ break;
+
+ case SMALL_ATOM_UTF8_EXT:
+ proto_tree_add_item_ret_uint(tree, hf_erldp_atom_length, tvb, offset, 1, ENC_BIG_ENDIAN, &len);
+ offset++;
+ proto_tree_add_item_ret_string(tree, hf_erldp_atom_text, tvb, offset, len, ENC_NA|ENC_UTF_8, wmem_packet_scope(), &str_val);
+ offset += len;
+ if (value_str)
+ *value_str = (const gchar *)str_val;
+ break;
+
+ case PORT_EXT:
+ offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
+ proto_tree_add_item(tree, hf_erldp_port_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(tree, hf_erldp_port_ext_creation, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ break;
+
+ case NEW_PORT_EXT:
+ offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
+ proto_tree_add_item(tree, hf_erldp_port_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(tree, hf_erldp_port_ext_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ break;
+
+ case PID_EXT:
+ offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
+ proto_tree_add_item(tree, hf_erldp_pid_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(tree, hf_erldp_pid_ext_serial, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(tree, hf_erldp_pid_ext_creation, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ break;
+
+ case NEW_PID_EXT:
+ offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
+ proto_tree_add_item(tree, hf_erldp_pid_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(tree, hf_erldp_pid_ext_serial, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(tree, hf_erldp_pid_ext_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ break;
+
+ case SMALL_TUPLE_EXT:
+ offset = dissect_etf_tuple_content(FALSE, pinfo, tvb, offset, tree, value_str);
+ break;
+
+ case LARGE_TUPLE_EXT:
+ offset = dissect_etf_tuple_content(TRUE, pinfo, tvb, offset, tree, value_str);
+ break;
+
+ case NIL_EXT:
+ break;
+
+ case LIST_EXT:
+ proto_tree_add_item_ret_uint(tree, hf_erldp_list_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
+ offset += 4;
+ for (i=0; i<len; i++) {
+ offset = dissect_etf_type(NULL, pinfo, tvb, offset, tree);
+ }
+ offset = dissect_etf_type("Tail", pinfo, tvb, offset, tree);
+ break;
+
+ case BINARY_EXT:
+ proto_tree_add_item_ret_uint(tree, hf_erldp_binary_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
+ offset += 4;
+ proto_tree_add_item(tree, hf_erldp_binary_ext, tvb, offset, len, ENC_NA);
+ offset += len;
+ break;
+
+ case NEW_REFERENCE_EXT:
+ proto_tree_add_item_ret_uint(tree, hf_erldp_new_ref_ext_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
+ offset += 2;
+ offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
+ proto_tree_add_item(tree, hf_erldp_new_ref_ext_creation, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ for (i=0; i<len; i++) {
+ id = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_erldp_new_ref_ext_id, tvb, offset, 4,
+ id, "ID[%d]: 0x%08X", i, id);
+ offset += 4;
+ }
+ break;
+
+ case NEWER_REFERENCE_EXT:
+ proto_tree_add_item_ret_uint(tree, hf_erldp_new_ref_ext_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
+ offset += 2;
+ offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
+ proto_tree_add_item(tree, hf_erldp_new_ref_ext_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ for (i=0; i<len; i++) {
+ id = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_erldp_new_ref_ext_id, tvb, offset, 4,
+ id, "ID[%d]: 0x%08X", i, id);
+ offset += 4;
+ }
+ break;
+
+ case FUN_EXT:
+ proto_tree_add_item_ret_uint(tree, hf_erldp_fun_ext_num_free, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
+ offset += 4;
+ offset = dissect_etf_type("Pid", pinfo, tvb, offset, tree);
+ offset = dissect_etf_type("Module", pinfo, tvb, offset, tree);
+ offset = dissect_etf_type("Index", pinfo, tvb, offset, tree);
+ offset = dissect_etf_type("Unique", pinfo, tvb, offset, tree);
+
+ for (i = 0; i < len; i++) {
+ gchar buf[ITEM_LABEL_LENGTH];
+ snprintf(buf, sizeof(buf), "Free Var[%u]", i + 1);
+ offset = dissect_etf_type(buf, pinfo, tvb, offset, tree);
+ }
+ break;
+
+ case NEW_FUN_EXT:
+ proto_tree_add_item(tree, hf_erldp_new_fun_ext_size, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(tree, hf_erldp_new_fun_ext_arity, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(tree, hf_erldp_new_fun_ext_uniq, tvb, offset, 16, ENC_NA);
+ offset += 16;
+ proto_tree_add_item(tree, hf_erldp_new_fun_ext_index, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item_ret_uint(tree, hf_erldp_new_fun_ext_num_free, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
+ offset += 4;
+ offset = dissect_etf_type("Module", pinfo, tvb, offset, tree);
+ offset = dissect_etf_type("OldIndex", pinfo, tvb, offset, tree);
+ offset = dissect_etf_type("OldUnique", pinfo, tvb, offset, tree);
+ offset = dissect_etf_type("Pid", pinfo, tvb, offset, tree);
+
+ for (i = 0; i < len; i++) {
+ gchar buf[ITEM_LABEL_LENGTH];
+ snprintf(buf, sizeof(buf), "Free Var[%u]", i + 1);
+ offset = dissect_etf_type(buf, pinfo, tvb, offset, tree);
+ }
+ break;
+ }
+
+ return offset;
+}
+
+static gint dissect_etf_pdu_data(packet_info *pinfo, tvbuff_t *tvb, gint offset, proto_tree *tree) {
+ guint8 ctl_op;
+
+ if ((tvb_get_guint8(tvb, offset) == SMALL_TUPLE_EXT) && (tvb_get_guint8(tvb, offset + 2) == SMALL_INTEGER_EXT)) {
+ ctl_op = tvb_get_guint8(tvb, offset + 3);
+ col_add_str(pinfo->cinfo, COL_INFO, val_to_str(ctl_op, VALS(erldp_ctlmsg_vals), "unknown ControlMessage operation (%d)"));
+ }
+ offset = dissect_etf_type("ControlMessage", pinfo, tvb, offset, tree);
+ if (tvb_reported_length_remaining(tvb, offset) > 0)
+ offset = dissect_etf_type("Message", pinfo, tvb, offset, tree);
+
+ return offset;
+}
+
+static gint dissect_etf_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const gchar *label) {
+ gint offset = 0;
+ guint8 mag;
+ guint32 tag;
+ proto_item *ti;
+ proto_tree *etf_tree;
+
+ mag = tvb_get_guint8(tvb, offset);
+ if (mag != VERSION_MAGIC) {
+ return 0;
+ }
+
+ etf_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_etf, &ti, (label) ? label : "External Term Format");
+
+ proto_tree_add_item(etf_tree, hf_etf_version_magic, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+
+ proto_tree_add_item_ret_uint(etf_tree, hf_etf_dist_header_tag, tvb, offset, 1, ENC_BIG_ENDIAN, &tag);
+ offset++;
+
+ if (!label)
+ proto_item_set_text(ti, "%s", val_to_str(tag, VALS(etf_header_tag_vals), "unknown tag (%d)"));
+
+ switch (tag) {
+ case DIST_HEADER:
+ offset = dissect_etf_dist_header(pinfo, tvb, offset, etf_tree);
+ proto_item_set_len(ti, offset);
+
+ dissect_etf_pdu_data(pinfo, tvb, offset, tree);
+ break;
+
+ case DIST_FRAG_HEADER:
+ case DIST_FRAG_CONT:
+ {
+ guint64 sequence_id, fragment_id;
+ gboolean save_fragmented;
+ fragment_head *frag_msg = NULL;
+ tvbuff_t *next_tvb = NULL;
+ gint len_rem;
+
+ proto_tree_add_item_ret_uint64(etf_tree, hf_erldp_sequence_id, tvb, offset, 8, ENC_BIG_ENDIAN, &sequence_id);
+ offset += 8;
+
+ proto_tree_add_item_ret_uint64(etf_tree, hf_erldp_fragment_id, tvb, offset, 8, ENC_BIG_ENDIAN, &fragment_id);
+ offset += 8;
+
+ save_fragmented = pinfo->fragmented;
+
+ len_rem = tvb_reported_length_remaining(tvb, offset);
+ if (len_rem <= 0)
+ return offset;
+
+ pinfo->fragmented = TRUE;
+
+ frag_msg = fragment_add_seq_next(&erldp_reassembly_table,
+ tvb, offset, pinfo, (guint32)sequence_id, NULL,
+ len_rem, fragment_id != 1);
+
+ next_tvb = process_reassembled_data(tvb, offset, pinfo,
+ "Reassembled ErlDP", frag_msg,
+ &etf_frag_items, NULL, tree);
+
+ if (next_tvb == NULL)
+ { /* make a new subset */
+ next_tvb = tvb_new_subset_remaining(tvb, offset);
+ call_data_dissector(next_tvb, pinfo, tree);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (Fragment ID: %" PRIu64 ")", fragment_id);
+ }
+ else
+ {
+ offset = dissect_etf_dist_header(pinfo, next_tvb, 0, etf_tree);
+ proto_item_set_len(ti, offset);
+
+ dissect_etf_pdu_data(pinfo, next_tvb, offset, tree);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (Reassembled, Fragment ID: %" PRIu64 ")", fragment_id);
+ }
+
+ pinfo->fragmented = save_fragmented;
+ offset = tvb_reported_length_remaining(tvb, offset);
+ break;
+ }
+ }
+
+ return offset;
+}
+
+static gint dissect_etf_versioned_type(const gchar *label, packet_info *pinfo, tvbuff_t *tvb, gint offset, proto_tree *tree) {
+ if (tvb_get_guint8(tvb, offset) != VERSION_MAGIC) {
+ proto_tree_add_item(tree, hf_erldp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ col_set_str(pinfo->cinfo, COL_INFO, "unknown header format");
+ return offset + 1;
+ }
+ offset += 1;
+
+ return dissect_etf_type(label, pinfo, tvb, offset, tree);
+}
+
+static gint dissect_etf_type(const gchar *label, packet_info *pinfo, tvbuff_t *tvb, gint offset, proto_tree *tree) {
+ gint begin = offset;
+ guint32 tag;
+ proto_item *ti;
+ proto_tree *etf_tree;
+ const gchar *value_str = NULL;
+
+ etf_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_etf, &ti, (label) ? label : "External Term Format");
+
+ proto_tree_add_item_ret_uint(etf_tree, hf_etf_tag, tvb, offset, 1, ENC_BIG_ENDIAN, &tag);
+ offset++;
+
+ if (!label)
+ proto_item_set_text(ti, "%s", val_to_str(tag, VALS(etf_tag_vals), "unknown tag (%d)"));
+
+ offset = dissect_etf_type_content(tag, pinfo, tvb, offset, etf_tree, &value_str);
+ if (value_str)
+ proto_item_append_text(ti, ": %s", value_str);
+
+ proto_item_set_len(ti, offset - begin);
+
+ return offset;
+}
+
+static gboolean is_handshake(tvbuff_t *tvb, int offset) {
+ guint32 len = tvb_get_ntohs(tvb, offset);
+ guint8 tag = tvb_get_guint8(tvb, offset + 2);
+ return ((len > 0) && strchr("nNras", tag) && (len == (guint32)tvb_captured_length_remaining(tvb, offset + 2)));
+}
+
+/*--- dissect_erldp_handshake -------------------------------------------------*/
+static void dissect_erldp_handshake(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ gint offset = 0;
+ guint32 tag;
+ gboolean is_challenge = FALSE;
+ guint32 str_len;
+ const guint8 *str;
+
+ static int * const erldp_flags_flags[] = {
+ &hf_erldp_flags_spare,
+ &hf_erldp_flags_alias,
+ &hf_erldp_flags_v4_nc,
+ &hf_erldp_flags_name_me,
+ &hf_erldp_flags_spawn,
+ &hf_erldp_flags_reserved,
+ &hf_erldp_flags_unlink_id,
+ &hf_erldp_flags_handshake_23,
+ &hf_erldp_flags_fragments,
+ &hf_erldp_flags_exit_payload,
+ &hf_erldp_flags_pending_connect,
+ &hf_erldp_flags_big_seqtrace_labels,
+ &hf_erldp_flags_send_sender,
+ &hf_erldp_flags_big_creation,
+ &hf_erldp_flags_map_tag,
+ &hf_erldp_flags_utf8_atoms,
+ &hf_erldp_flags_ets_compressed,
+ &hf_erldp_flags_small_atom_tags,
+ &hf_erldp_flags_dist_hdr_atom_cache,
+ &hf_erldp_flags_unicode_io,
+ &hf_erldp_flags_new_floats,
+ &hf_erldp_flags_bit_binaries,
+ &hf_erldp_flags_export_ptr_tag,
+ &hf_erldp_flags_extended_pids_ports,
+ &hf_erldp_flags_new_fun_tags,
+ &hf_erldp_flags_hidden_atom_cache,
+ &hf_erldp_flags_dist_monitor_name,
+ &hf_erldp_flags_fun_tags,
+ &hf_erldp_flags_dist_monitor,
+ &hf_erldp_flags_extended_references,
+ &hf_erldp_flags_atom_cache,
+ &hf_erldp_flags_published,
+ NULL
+ };
+
+ proto_tree_add_item(tree, hf_erldp_length_2, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item_ret_uint(tree, hf_erldp_tag, tvb, offset, 1, ENC_ASCII|ENC_NA, &tag);
+ offset++;
+
+ switch (tag) {
+ case 'n' :
+ proto_tree_add_item(tree, hf_erldp_version, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_erldp_flags_v5,
+ ett_erldp_flags, erldp_flags_flags, ENC_BIG_ENDIAN);
+ offset += 4;
+ if (tvb_bytes_exist(tvb, offset, 4)) {
+ if (!tvb_ascii_isprint(tvb, offset, 4)) {
+ is_challenge = TRUE;
+ }
+ }
+ if (is_challenge) {
+ proto_tree_add_item(tree, hf_erldp_challenge, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ }
+ str_len = tvb_captured_length_remaining(tvb, offset);
+ proto_tree_add_item_ret_string(tree, hf_erldp_name, tvb, offset, str_len, ENC_ASCII|ENC_NA, wmem_packet_scope(), &str);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", (is_challenge) ? "SEND_CHALLENGE" : "SEND_NAME", str);
+ break;
+
+ case 'N':
+ proto_tree_add_bitmask(tree, tvb, offset, hf_erldp_flags_v6,
+ ett_erldp_flags, erldp_flags_flags, ENC_BIG_ENDIAN);
+ offset += 8;
+ if (tvb_bytes_exist(tvb, offset + 6, 4)) {
+ if (!tvb_ascii_isprint(tvb, offset + 6, 4)) {
+ is_challenge = TRUE;
+ }
+ }
+ if (is_challenge) {
+ proto_tree_add_item(tree, hf_erldp_challenge, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ }
+ proto_tree_add_item(tree, hf_erldp_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item_ret_uint(tree, hf_erldp_nlen, tvb, offset, 2, ENC_BIG_ENDIAN, &str_len);
+ offset += 2;
+ proto_tree_add_item_ret_string(tree, hf_erldp_name, tvb, offset, str_len, ENC_ASCII|ENC_NA, wmem_packet_scope(), &str);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", (is_challenge) ? "SEND_CHALLENGE" : "SEND_NAME", str);
+ break;
+
+ case 'r' :
+ proto_tree_add_item(tree, hf_erldp_challenge, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(tree, hf_erldp_digest, tvb, offset, 16, ENC_NA);
+ /*offset += 16;*/
+ col_set_str(pinfo->cinfo, COL_INFO, "SEND_CHALLENGE_REPLY");
+ break;
+
+ case 'a' :
+ proto_tree_add_item(tree, hf_erldp_digest, tvb, offset, 16, ENC_NA);
+ /*offset += 16;*/
+ col_set_str(pinfo->cinfo, COL_INFO, "SEND_CHALLENGE_ACK");
+ break;
+
+ case 's' :
+ str_len = tvb_captured_length_remaining(tvb, offset);
+ proto_tree_add_item_ret_string(tree, hf_erldp_status, tvb, offset, str_len, ENC_ASCII|ENC_NA, wmem_packet_scope(), &str);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "SEND_STATUS %s", str);
+ break;
+ }
+}
+
+/*--- dissect_erldp_pdu -------------------------------------------------*/
+static int dissect_erldp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
+ gint offset;
+ guint32 msg_len;
+ guint8 type;
+ proto_tree *erldp_tree;
+ proto_item *ti;
+ tvbuff_t *next_tvb = NULL;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
+
+ ti = proto_tree_add_item(tree, proto_erldp, tvb, 0, -1, ENC_NA);
+ erldp_tree = proto_item_add_subtree(ti, ett_erldp);
+
+ if (is_handshake(tvb, 0)) {
+ dissect_erldp_handshake(tvb, pinfo, erldp_tree);
+ return tvb_captured_length(tvb);
+ }
+
+ offset = 0;
+
+ proto_tree_add_item_ret_uint(erldp_tree, hf_erldp_length_4, tvb, offset, 4, ENC_BIG_ENDIAN, &msg_len);
+ offset += 4;
+
+ if (msg_len == 0) {
+ col_set_str(pinfo->cinfo, COL_INFO, "KEEP_ALIVE");
+ return offset;
+ }
+
+ type = tvb_get_guint8(tvb, offset);
+ switch (type) {
+ case ERL_PASS_THROUGH:
+ proto_tree_add_item(erldp_tree, hf_erldp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ offset = dissect_etf_versioned_type("ControlMessage", pinfo, tvb, offset, erldp_tree);
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ dissect_etf_versioned_type("Message", pinfo, tvb, offset, erldp_tree);
+ }
+ break;
+
+ case VERSION_MAGIC:
+ next_tvb = tvb_new_subset_length_caplen(tvb, offset, -1, 4 + msg_len - offset);
+ dissect_etf_pdu(next_tvb, pinfo, erldp_tree, "DistributionHeader");
+ break;
+
+ default:
+ proto_tree_add_item(erldp_tree, hf_erldp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ col_set_str(pinfo->cinfo, COL_INFO, "unknown header format");
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+/*--- get_erldp_pdu_len -------------------------------------------------*/
+static guint get_erldp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
+ int offset, void *data _U_)
+{
+ if (is_handshake(tvb, offset))
+ return(2 + tvb_get_ntohs(tvb, offset));
+
+ return(4 + tvb_get_ntohl(tvb, offset));
+}
+
+/*--- dissect_erldp -------------------------------------------------*/
+static int
+dissect_erldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) {
+ tcp_dissect_pdus(tvb, pinfo, tree,
+ erldp_desegment, /* desegment or not */
+ 4, /* fixed-length part of the PDU */
+ get_erldp_pdu_len, /* routine to get the length of the PDU */
+ dissect_erldp_pdu, data); /* routine to dissect a PDU */
+ return tvb_captured_length(tvb);
+}
+
+/*--- proto_register_erldp ----------------------------------------------*/
+void proto_register_erldp(void) {
+ /* module_t *erldp_module; */
+
+ /* List of fields */
+ static hf_register_info hf[] = {
+ /*--- Handshake fields ---*/
+ { &hf_erldp_length_2, { "Length", "erldp.len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Message Length", HFILL}},
+ { &hf_etf_version_magic, { "VERSION_MAGIC", "erldp.version_magic",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_tag, { "Tag", "erldp.tag",
+ FT_CHAR, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_type, { "Type", "erldp.type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_version, { "Version", "erldp.version",
+ FT_UINT16, BASE_DEC, VALS(epmd_version_vals), 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_flags_v5, { "Flags", "erldp.flags_v5",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_flags_v6, { "Flags", "erldp.flags_v6",
+ FT_UINT64, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_flags_published, { "Published", "erldp.flags.published",
+ FT_BOOLEAN, 64, NULL, 0x1,
+ NULL, HFILL }},
+ { &hf_erldp_flags_atom_cache, { "Atom Cache", "erldp.flags.atom_cache",
+ FT_BOOLEAN, 64, NULL, 0x2,
+ NULL, HFILL }},
+ { &hf_erldp_flags_extended_references, { "Extended References", "erldp.flags.extended_references",
+ FT_BOOLEAN, 64, NULL, 0x4,
+ NULL, HFILL }},
+ { &hf_erldp_flags_dist_monitor, { "Dist Monitor", "erldp.flags.dist_monitor",
+ FT_BOOLEAN, 64, NULL, 0x8,
+ NULL, HFILL }},
+ { &hf_erldp_flags_fun_tags, { "Fun Tags", "erldp.flags.fun_tags",
+ FT_BOOLEAN, 64, NULL, 0x10,
+ NULL, HFILL }},
+ { &hf_erldp_flags_dist_monitor_name, { "Dist Monitor Name", "erldp.flags.dist_monitor_name",
+ FT_BOOLEAN, 64, NULL, 0x20,
+ NULL, HFILL }},
+ { &hf_erldp_flags_hidden_atom_cache, { "Hidden Atom Cache", "erldp.flags.hidden_atom_cache",
+ FT_BOOLEAN, 64, NULL, 0x40,
+ NULL, HFILL }},
+ { &hf_erldp_flags_new_fun_tags, { "New Fun Tags", "erldp.flags.new_fun_tags",
+ FT_BOOLEAN, 64, NULL, 0x80,
+ NULL, HFILL }},
+ { &hf_erldp_flags_extended_pids_ports, { "Extended Pids Ports", "erldp.flags.extended_pids_ports",
+ FT_BOOLEAN, 64, NULL, 0x100,
+ NULL, HFILL }},
+ { &hf_erldp_flags_export_ptr_tag, { "Export PTR Tag", "erldp.flags.export_ptr_tag",
+ FT_BOOLEAN, 64, NULL, 0x200,
+ NULL, HFILL }},
+ { &hf_erldp_flags_bit_binaries, { "Bit Binaries", "erldp.flags.bit_binaries",
+ FT_BOOLEAN, 64, NULL, 0x400,
+ NULL, HFILL }},
+ { &hf_erldp_flags_new_floats, { "New Floats", "erldp.flags.new_floats",
+ FT_BOOLEAN, 64, NULL, 0x800,
+ NULL, HFILL }},
+ { &hf_erldp_flags_unicode_io, { "Unicode IO", "erldp.flags.unicode_io",
+ FT_BOOLEAN, 64, NULL, 0x1000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_dist_hdr_atom_cache, { "Dist HDR Atom Cache", "erldp.flags.dist_hdr_atom_cache",
+ FT_BOOLEAN, 64, NULL, 0x2000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_small_atom_tags, { "Small Atom Tags", "erldp.flags.small_atom_tags",
+ FT_BOOLEAN, 64, NULL, 0x4000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_ets_compressed, { "ETS Compressed", "erldp.flags.ets_compressed",
+ FT_BOOLEAN, 64, NULL, 0x8000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_utf8_atoms, { "UTF8 Atoms", "erldp.flags.utf8_atoms",
+ FT_BOOLEAN, 64, NULL, 0x10000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_map_tag, { "Map Tag", "erldp.flags.map_tag",
+ FT_BOOLEAN, 64, NULL, 0x20000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_big_creation, { "Big Creation", "erldp.flags.big_creation",
+ FT_BOOLEAN, 64, NULL, 0x40000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_send_sender, { "Send Sender", "erldp.flags.send_sender",
+ FT_BOOLEAN, 64, NULL, 0x80000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_big_seqtrace_labels, { "Big Seqtrace Labels", "erldp.flags.big_seqtrace_labels",
+ FT_BOOLEAN, 64, NULL, 0x100000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_pending_connect, { "Pending Connect", "erldp.flags.pending_connect",
+ FT_BOOLEAN, 64, NULL, 0x200000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_exit_payload, { "Exit Payload", "erldp.flags.exit_payload",
+ FT_BOOLEAN, 64, NULL, 0x400000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_fragments, { "Fragments", "erldp.flags.fragments",
+ FT_BOOLEAN, 64, NULL, 0x800000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_handshake_23, { "Handshake 23", "erldp.flags.handshake_23",
+ FT_BOOLEAN, 64, NULL, 0x1000000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_unlink_id, { "Unlink Id", "erldp.flags.unlink_id",
+ FT_BOOLEAN, 64, NULL, 0x2000000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_reserved, { "Reserved", "erldp.flags.reserved",
+ FT_UINT64, BASE_DEC, NULL, 0xfc000000,
+ NULL, HFILL }},
+ { &hf_erldp_flags_spawn, { "Spawn", "erldp.flags.spawn",
+ FT_BOOLEAN, 64, NULL, 1ULL << 32,
+ NULL, HFILL }},
+ { &hf_erldp_flags_name_me, { "Name ME", "erldp.flags.name_me",
+ FT_BOOLEAN, 64, NULL, 1ULL << 33,
+ NULL, HFILL }},
+ { &hf_erldp_flags_v4_nc, { "V4 NC", "erldp.flags.v4_nc",
+ FT_BOOLEAN, 64, NULL, 1ULL << 34,
+ NULL, HFILL }},
+ { &hf_erldp_flags_alias, { "Alias", "erldp.flags.alias",
+ FT_BOOLEAN, 64, NULL, 1ULL << 35,
+ NULL, HFILL }},
+ { &hf_erldp_flags_spare, { "Spare", "erldp.flags.spare",
+ FT_UINT64, BASE_DEC, NULL, ~(0ULL) << 36,
+ NULL, HFILL }},
+ { &hf_erldp_creation, { "Creation", "erldp.creation",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_challenge, { "Challenge", "erldp.challenge",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_digest, { "Digest", "erldp.digest",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_nlen, { "Name Length", "erldp.nlen",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_name, { "Name", "erldp.name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_status, { "Status", "erldp.status",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_sequence_id, { "Sequence Id", "erldp.sequence_id",
+ FT_UINT64, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_fragment_id, { "Fragment Id", "erldp.fragment_id",
+ FT_UINT64, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_num_atom_cache_refs, { "NumberOfAtomCacheRefs", "erldp.num_atom_cache_refs",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_etf_flags, { "Flags", "erldp.etf_flags",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_internal_segment_index, { "InternalSegmentIndex", "erldp.internal_segment_index",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_atom_length, { "Length", "erldp.atom_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_atom_length2, { "Length", "erldp.atom_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_atom_text, { "AtomText", "erldp.atom_text",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_atom_cache_ref, { "AtomCacheReferenceIndex", "erldp.atom_cache_ref",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_small_int_ext, { "Int", "erldp.small_int_ext",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_int_ext, { "Int", "erldp.int_ext",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_small_big_ext_len, { "Len", "erldp.small_big_ext_len",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_large_big_ext_len, { "Len", "erldp.large_big_ext_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_big_ext_int, { "Int", "erldp.big_ext_int",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_big_ext_str, { "Int", "erldp.big_ext_str",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_big_ext_bytes, { "Int", "erldp.big_ext_bytes",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_float_ext, { "Float", "erldp.float_ext",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_new_float_ext, { "Float", "erldp.new_float_ext",
+ FT_DOUBLE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_port_ext_id, { "ID", "erldp.port_ext.id",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_port_ext_creation, { "Creation", "erldp.port_ext.creation",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_pid_ext_id, { "ID", "erldp.pid_ext.id",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_pid_ext_serial, { "Serial", "erldp.pid_ext.serial",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_pid_ext_creation, { "Creation", "erldp.pid_ext.creation",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_list_ext_len, { "Len", "erldp.list_ext.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_binary_ext_len, { "Len", "erldp.binary_ext.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_binary_ext, { "Binary", "erldp.binary_ext",
+ FT_BYTES, BASE_SHOW_ASCII_PRINTABLE, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_new_ref_ext_len, { "Len", "erldp.new_ref_ext.len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_new_ref_ext_creation, { "Creation", "erldp.new_ref_ext.creation",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_new_ref_ext_id, { "ID", "erldp.new_ref_ext.id",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_fun_ext_num_free, { "Num Free", "erldp.fun_ext.num_free",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_new_fun_ext_size, { "Size", "erldp.new_fun_ext.size",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_new_fun_ext_arity, { "Arity", "erldp.new_fun_ext.arity",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_new_fun_ext_uniq, { "Uniq", "erldp.new_fun_ext.uniq",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_new_fun_ext_index, { "Index", "erldp.new_fun_ext.index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ { &hf_erldp_new_fun_ext_num_free, { "Num Free", "erldp.new_fun_ext.num_free",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+
+ /*--- ---*/
+ { &hf_erldp_length_4, { "Length", "erldp.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Message Length", HFILL}},
+
+ /*--- ETF ---*/
+ { &hf_etf_tag, { "Tag", "erldp.etf_tag",
+ FT_UINT8, BASE_DEC, VALS(etf_tag_vals), 0x0,
+ NULL, HFILL}},
+ { &hf_etf_dist_header_tag, { "Tag", "erldp.etf_header_tag",
+ FT_UINT8, BASE_DEC, VALS(etf_header_tag_vals), 0x0,
+ NULL, HFILL}},
+
+ { &hf_etf_dist_header_new_cache, { "NewCacheEntryFlag", "erldp.dist_header.new_cache",
+ FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x08,
+ NULL, HFILL}},
+
+ { &hf_etf_dist_header_segment_index, { "SegmentIndex", "erldp.dist_header.segment_index",
+ FT_UINT8, BASE_DEC, NULL, 0x7,
+ NULL, HFILL}},
+
+ { &hf_etf_dist_header_long_atoms, { "LongAtoms", "erldp.dist_header.new_cache",
+ FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x12,
+ NULL, HFILL}},
+
+ { &hf_etf_arity4, { "Arity", "erldp.arity",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+
+ { &hf_etf_arity, { "Arity", "erldp.arity",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}},
+
+ { &hf_etf_fragments, { "Message fragments", "erldp.dist.fragments",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL,
+ HFILL }},
+
+ { &hf_etf_fragment, { "Message fragment", "erldp.dist.fragment",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_etf_fragment_overlap, { "Message fragment overlap", "erldp.dist.fragment.overlap",
+ FT_BOOLEAN, 0, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_etf_fragment_overlap_conflicts, { "Message fragment overlapping with conflicting data",
+ "erldp.dist.fragment.overlap.conflicts",
+ FT_BOOLEAN, 0, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_etf_fragment_multiple_tails, { "Message has multiple tail fragments",
+ "erldp.dist.fragment.multiple_tails",
+ FT_BOOLEAN, 0, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_etf_fragment_too_long_fragment, { "Message fragment too long", "erldp.dist.fragment.too_long_fragment",
+ FT_BOOLEAN, 0, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_etf_fragment_error, { "Message defragmentation error", "erldp.dist.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_etf_fragment_count, { "Message fragment count", "erldp.dist.fragment.count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_etf_reassembled_in, { "Reassembled in", "erldp.dist.reassembled.in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_etf_reassembled_length, { "Reassembled length", "erldp.dist.reassembled.length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_etf_reassembled_data, { "Reassembled data", "erldp.dist.reassembled.data",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ };
+
+ /* List of subtrees */
+ static gint *ett[] = {
+ &ett_erldp,
+ &ett_erldp_flags,
+ &ett_etf,
+ &ett_etf_flags,
+ &ett_etf_acrs,
+ &ett_etf_acr,
+ &ett_etf_tmp,
+ &ett_etf_fragment,
+ &ett_etf_fragments,
+ };
+
+ /* Register protocol and dissector */
+ proto_erldp = proto_register_protocol(PNAME, PSNAME, PFNAME);
+ reassembly_table_register(&erldp_reassembly_table,
+ &addresses_reassembly_table_functions);
+
+ erldp_handle = register_dissector(PFNAME, dissect_erldp, proto_erldp);
+
+ /* Register fields and subtrees */
+ proto_register_field_array(proto_erldp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+/*--- proto_reg_handoff_erldp -------------------------------------------*/
+void proto_reg_handoff_erldp(void) {
+
+ dissector_add_for_decode_as_with_preference("tcp.port", erldp_handle);
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local Variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=2 tabstop=8 expandtab:
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */