Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-erldp.c
blob56bab2568b740e93459fee397391fa9d85d296cc
1 /* packet-erldp.c
2 * Erlang Distribution Protocol
3 * http://www.erlang.org/doc/apps/erts/erl_dist_protocol.html
5 * 2010 Tomas Kukosa
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include "config.h"
17 #include <epan/packet.h>
18 #include <epan/tfs.h>
19 #include <epan/reassemble.h>
20 #include "packet-tcp.h"
21 #include "packet-epmd.h"
23 #define ERL_PASS_THROUGH 'p'
25 #define VERSION_MAGIC 131 /* 130 in erlang 4.2 */
27 #define SMALL_INTEGER_EXT 'a'
28 #define INTEGER_EXT 'b'
29 #define FLOAT_EXT 'c'
30 #define ATOM_EXT 'd'
31 #define ATOM_UTF8_EXT 'v'
32 #define SMALL_ATOM_EXT 's'
33 #define SMALL_ATOM_UTF8_EXT 'w'
34 #define REFERENCE_EXT 'e'
35 #define NEW_REFERENCE_EXT 'r'
36 #define NEWER_REFERENCE_EXT 'Z'
37 #define PORT_EXT 'f'
38 #define NEW_PORT_EXT 'Y'
39 #define V4_PORT_EXT 'x'
40 #define NEW_FLOAT_EXT 'F'
41 #define PID_EXT 'g'
42 #define NEW_PID_EXT 'X'
43 #define SMALL_TUPLE_EXT 'h'
44 #define LARGE_TUPLE_EXT 'i'
45 #define NIL_EXT 'j'
46 #define STRING_EXT 'k'
47 #define LIST_EXT 'l'
48 #define BINARY_EXT 'm'
49 #define BIT_BINARY_EXT 'M'
50 #define SMALL_BIG_EXT 'n'
51 #define LARGE_BIG_EXT 'o'
52 #define NEW_FUN_EXT 'p'
53 #define EXPORT_EXT 'q'
54 #define FUN_EXT 'u'
55 #define MAP_EXT 't'
56 #define LOCAL_EXT 'y'
58 #define DIST_HEADER 'D'
59 #define DIST_FRAG_HEADER 'E'
60 #define DIST_FRAG_CONT 'F'
61 #define ATOM_CACHE_REF 'R'
62 #define COMPRESSED 'P'
64 #define PNAME "Erlang Distribution Protocol"
65 #define PSNAME "ErlDP"
66 #define PFNAME "erldp"
68 void proto_register_erldp(void);
69 void proto_reg_handoff_erldp(void);
71 static const value_string etf_tag_vals[] = {
72 { SMALL_INTEGER_EXT , "SMALL_INTEGER_EXT" },
73 { INTEGER_EXT , "INTEGER_EXT" },
74 { FLOAT_EXT , "FLOAT_EXT" },
75 { ATOM_EXT , "ATOM_EXT" },
76 { ATOM_UTF8_EXT , "ATOM_UTF8_EXT" },
77 { SMALL_ATOM_EXT , "SMALL_ATOM_EXT" },
78 { SMALL_ATOM_UTF8_EXT , "SMALL_ATOM_UTF8_EXT" },
79 { REFERENCE_EXT , "REFERENCE_EXT" },
80 { NEW_REFERENCE_EXT , "NEW_REFERENCE_EXT" },
81 { NEWER_REFERENCE_EXT , "NEWER_REFERENCE_EXT" },
82 { PORT_EXT , "PORT_EXT" },
83 { NEW_PORT_EXT , "NEW_PORT_EXT" },
84 { V4_PORT_EXT , "V4_PORT_EXT" },
85 { NEW_FLOAT_EXT , "NEW_FLOAT_EXT" },
86 { PID_EXT , "PID_EXT" },
87 { NEW_PID_EXT , "NEW_PID_EXT" },
88 { SMALL_TUPLE_EXT , "SMALL_TUPLE_EXT" },
89 { LARGE_TUPLE_EXT , "LARGE_TUPLE_EXT" },
90 { NIL_EXT , "NIL_EXT" },
91 { STRING_EXT , "STRING_EXT" },
92 { LIST_EXT , "LIST_EXT" },
93 { BINARY_EXT , "BINARY_EXT" },
94 { BIT_BINARY_EXT , "BIT_BINARY_EXT" },
95 { SMALL_BIG_EXT , "SMALL_BIG_EXT" },
96 { LARGE_BIG_EXT , "LARGE_BIG_EXT" },
97 { NEW_FUN_EXT , "NEW_FUN_EXT" },
98 { EXPORT_EXT , "EXPORT_EXT" },
99 { FUN_EXT , "FUN_EXT" },
100 { MAP_EXT , "MAP_EXT" },
101 { LOCAL_EXT , "LOCAL_EXT" },
102 { DIST_HEADER , "DIST_HEADER" },
103 { DIST_FRAG_HEADER , "DIST_FRAG_HEADER" },
104 { ATOM_CACHE_REF , "ATOM_CACHE_REF" },
105 { COMPRESSED , "COMPRESSED" },
106 { 0, NULL }
109 static const value_string etf_header_tag_vals[] = {
110 { DIST_HEADER , "DIST_HEADER" },
111 { DIST_FRAG_HEADER , "DIST_FRAG_HEADER" },
112 { DIST_FRAG_CONT , "DIST_FRAG_CONT" },
113 { 0, NULL }
116 static const value_string erldp_ctlmsg_vals[] = {
117 { 1, "LINK" },
118 { 2, "SEND" },
119 { 3, "EXIT" },
120 { 4, "UNLINK" },
121 { 5, "NODE_LINK" },
122 { 6, "REG_SEND" },
123 { 7, "GROUP_LEADER" },
124 { 8, "EXIT2" },
125 { 12, "SEND_TT" },
126 { 13, "EXIT_TT" },
127 { 16, "REG_SEND_TT" },
128 { 18, "EXIT2_TT" },
129 { 19, "MONITOR_P" },
130 { 20, "DEMONITOR_P" },
131 { 21, "MONITOR_P_EXIT" },
132 { 22, "SEND_SENDER" },
133 { 23, "SEND_SENDER_TT" },
134 { 24, "PAYLOAD_EXIT" },
135 { 25, "PAYLOAD_EXIT_TT" },
136 { 26, "PAYLOAD_EXIT2" },
137 { 27, "PAYLOAD_EXIT2_TT" },
138 { 28, "PAYLOAD_MONITOR_P_EXIT" },
139 { 29, "SPAWN_REQUEST" },
140 { 30, "SPAWN_REQUEST_TT" },
141 { 31, "SPAWN_REPLY" },
142 { 32, "SPAWN_REPLY_TT" },
143 { 0, NULL }
146 /* Initialize the protocol and registered fields */
147 static int proto_erldp;
148 static int hf_erldp_length_2;
149 static int hf_erldp_length_4;
150 static int hf_etf_version_magic;
151 static int hf_erldp_tag;
152 static int hf_erldp_type;
153 static int hf_erldp_version;
154 static int hf_erldp_flags_v5;
155 static int hf_erldp_flags_v6;
156 static int hf_erldp_flags_published;
157 static int hf_erldp_flags_atom_cache;
158 static int hf_erldp_flags_extended_references;
159 static int hf_erldp_flags_dist_monitor;
160 static int hf_erldp_flags_fun_tags;
161 static int hf_erldp_flags_dist_monitor_name;
162 static int hf_erldp_flags_hidden_atom_cache;
163 static int hf_erldp_flags_new_fun_tags;
164 static int hf_erldp_flags_extended_pids_ports;
165 static int hf_erldp_flags_export_ptr_tag;
166 static int hf_erldp_flags_bit_binaries;
167 static int hf_erldp_flags_new_floats;
168 static int hf_erldp_flags_unicode_io;
169 static int hf_erldp_flags_dist_hdr_atom_cache;
170 static int hf_erldp_flags_small_atom_tags;
171 static int hf_erldp_flags_ets_compressed;
172 static int hf_erldp_flags_utf8_atoms;
173 static int hf_erldp_flags_map_tag;
174 static int hf_erldp_flags_big_creation;
175 static int hf_erldp_flags_send_sender;
176 static int hf_erldp_flags_big_seqtrace_labels;
177 static int hf_erldp_flags_pending_connect;
178 static int hf_erldp_flags_exit_payload;
179 static int hf_erldp_flags_fragments;
180 static int hf_erldp_flags_handshake_23;
181 static int hf_erldp_flags_unlink_id;
182 static int hf_erldp_flags_reserved;
183 static int hf_erldp_flags_spawn;
184 static int hf_erldp_flags_name_me;
185 static int hf_erldp_flags_v4_nc;
186 static int hf_erldp_flags_alias;
187 static int hf_erldp_flags_spare;
188 static int hf_erldp_creation;
189 static int hf_erldp_challenge;
190 static int hf_erldp_digest;
191 static int hf_erldp_nlen;
192 static int hf_erldp_name;
193 static int hf_erldp_status;
194 static int hf_erldp_sequence_id;
195 static int hf_erldp_fragment_id;
196 static int hf_erldp_num_atom_cache_refs;
197 static int hf_erldp_etf_flags;
198 static int hf_erldp_internal_segment_index;
199 static int hf_erldp_atom_length;
200 static int hf_erldp_atom_length2;
201 static int hf_erldp_atom_text;
202 static int hf_erldp_string_ext_len;
203 static int hf_erldp_string_ext;
204 static int hf_erldp_atom_cache_ref;
205 static int hf_erldp_small_int_ext;
206 static int hf_erldp_int_ext;
207 static int hf_erldp_small_big_ext_len;
208 static int hf_erldp_large_big_ext_len;
209 static int hf_erldp_big_ext_int;
210 static int hf_erldp_big_ext_str;
211 static int hf_erldp_big_ext_bytes;
212 static int hf_erldp_float_ext;
213 static int hf_erldp_new_float_ext;
214 static int hf_erldp_port_ext_id;
215 static int hf_erldp_port_ext_v4_id;
216 static int hf_erldp_port_ext_creation;
217 static int hf_erldp_pid_ext_id;
218 static int hf_erldp_pid_ext_serial;
219 static int hf_erldp_pid_ext_creation;
220 static int hf_erldp_list_ext_len;
221 static int hf_erldp_map_ext_len;
222 static int hf_erldp_binary_ext_len;
223 static int hf_erldp_binary_ext_bits;
224 static int hf_erldp_binary_ext;
225 static int hf_erldp_new_ref_ext_len;
226 static int hf_erldp_new_ref_ext_creation;
227 static int hf_erldp_new_ref_ext_id;
228 static int hf_erldp_fun_ext_num_free;
229 static int hf_erldp_new_fun_ext_size;
230 static int hf_erldp_new_fun_ext_arity;
231 static int hf_erldp_new_fun_ext_uniq;
232 static int hf_erldp_new_fun_ext_index;
233 static int hf_erldp_new_fun_ext_num_free;
235 static int hf_etf_tag;
236 static int hf_etf_dist_header_tag;
237 static int hf_etf_dist_header_new_cache;
238 static int hf_etf_dist_header_segment_index;
239 static int hf_etf_dist_header_long_atoms;
240 static int hf_etf_arity4;
241 static int hf_etf_arity;
243 static int hf_etf_fragments;
244 static int hf_etf_fragment;
245 static int hf_etf_fragment_overlap;
246 static int hf_etf_fragment_overlap_conflicts;
247 static int hf_etf_fragment_multiple_tails;
248 static int hf_etf_fragment_too_long_fragment;
249 static int hf_etf_fragment_error;
250 static int hf_etf_fragment_count;
251 static int hf_etf_reassembled_in;
252 static int hf_etf_reassembled_length;
253 static int hf_etf_reassembled_data;
255 static reassembly_table erldp_reassembly_table;
257 /* Initialize the subtree pointers */
258 static int ett_erldp;
259 static int ett_erldp_flags;
261 static int ett_etf;
262 static int ett_etf_flags;
263 static int ett_etf_acrs;
264 static int ett_etf_acr;
265 static int ett_etf_tmp;
267 static int ett_etf_fragment;
268 static int ett_etf_fragments;
270 /* Preferences */
271 static bool erldp_desegment = true;
273 /* Dissectors */
274 static dissector_handle_t erldp_handle;
276 /* Defragmentation */
277 static const fragment_items etf_frag_items = {
278 /* Fragment subtrees */
279 &ett_etf_fragment,
280 &ett_etf_fragments,
281 /* Fragment fields */
282 &hf_etf_fragments,
283 &hf_etf_fragment,
284 &hf_etf_fragment_overlap,
285 &hf_etf_fragment_overlap_conflicts,
286 &hf_etf_fragment_multiple_tails,
287 &hf_etf_fragment_too_long_fragment,
288 &hf_etf_fragment_error,
289 &hf_etf_fragment_count,
290 /* Reassembled in field */
291 &hf_etf_reassembled_in,
292 /* Reassembled length field */
293 &hf_etf_reassembled_length,
294 &hf_etf_reassembled_data,
295 /* Tag */
296 "Message fragments"
299 /*--- External Term Format ---*/
301 static int dissect_etf_type(const char *label, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
302 static int dissect_etf_pdu_data(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
304 static int dissect_etf_dist_header(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree) {
305 uint32_t num, isi;
306 uint8_t flen, i, flg;
307 int flg_offset, acrs_offset, acr_offset;
308 uint32_t atom_txt_len;
309 bool new_entry, long_atom;
310 proto_item *ti_acrs, *ti_acr, *ti_tmp;
311 proto_tree *flags_tree, *acrs_tree, *acr_tree;
312 const uint8_t *str;
314 proto_tree_add_item_ret_uint(tree, hf_erldp_num_atom_cache_refs, tvb, offset, 1, ENC_BIG_ENDIAN, &num);
315 offset++;
317 if (num == 0)
318 return offset;
320 flg_offset = offset;
321 flen = num / 2 + 1;
322 ti_tmp = proto_tree_add_item(tree, hf_erldp_etf_flags, tvb, offset, flen, ENC_NA );
323 flags_tree = proto_item_add_subtree(ti_tmp, ett_etf_flags);
324 for (i=0; i<num; i++) {
325 flg = tvb_get_uint8(tvb, offset + i / 2);
326 proto_tree_add_boolean_format_value(flags_tree, hf_etf_dist_header_new_cache, tvb, offset + i / 2, 1,
327 (flg & (0x08 << 4*(i%2))), "NewCacheEntryFlag[%2d]: %s",
328 i, (flg & (0x08 << 4*(i%2))) ? "SET" : "---");
329 proto_tree_add_uint_format(flags_tree, hf_etf_dist_header_segment_index, tvb, offset + i / 2, 1,
330 (flg & (0x07 << 4*(i%2))), "SegmentIndex [%2d]: %u",
331 i, (flg & (0x07 << 4*(i%2))));
333 flg = tvb_get_uint8(tvb, offset + num / 2);
334 proto_tree_add_boolean(flags_tree, hf_etf_dist_header_long_atoms, tvb, offset + num / 2, 1, (flg & (0x01 << 4*(num%2))));
335 long_atom = flg & (0x01 << 4*(num%2));
336 offset += flen;
338 acrs_offset = offset;
339 acrs_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_etf_acrs, &ti_acrs, "AtomCacheRefs");
340 for (i=0; i<num; i++) {
341 flg = tvb_get_uint8(tvb, flg_offset + i / 2);
342 new_entry = flg & (0x08 << 4*(i%2));
343 acr_offset = offset;
344 acr_tree = proto_tree_add_subtree_format(acrs_tree, tvb, offset, 0, ett_etf_acr, &ti_acr, "AtomCacheRef[%2d]:", i);
345 proto_tree_add_item_ret_uint(acr_tree, hf_erldp_internal_segment_index, tvb, offset, 1, ENC_BIG_ENDIAN, &isi);
346 proto_item_append_text(ti_acr, " %3d", isi);
347 offset++;
348 if (!new_entry)
349 continue;
350 if (long_atom) {
351 proto_tree_add_item_ret_uint(acr_tree, hf_erldp_atom_length2, tvb, offset, 2, ENC_BIG_ENDIAN, &atom_txt_len);
352 offset += 2;
354 else {
355 proto_tree_add_item_ret_uint(acr_tree, hf_erldp_atom_length, tvb, offset, 1, ENC_BIG_ENDIAN, &atom_txt_len);
356 offset++;
358 proto_tree_add_item_ret_string(acr_tree, hf_erldp_atom_text, tvb, offset, atom_txt_len, ENC_NA|ENC_ASCII, pinfo->pool, &str);
359 proto_item_append_text(ti_acr, " - '%s'", str);
360 offset += atom_txt_len;
361 proto_item_set_len(ti_acr, offset - acr_offset);
363 proto_item_set_len(ti_acrs, offset - acrs_offset);
365 return offset;
368 // NOLINTNEXTLINE(misc-no-recursion)
369 static int dissect_etf_tuple_content(bool large, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree, const char **value_str _U_) {
370 uint32_t arity, i;
372 if (large) {
373 proto_tree_add_item_ret_uint(tree, hf_etf_arity4, tvb, offset, 4, ENC_BIG_ENDIAN, &arity);
374 offset += 4;
375 } else {
376 proto_tree_add_item_ret_uint(tree, hf_etf_arity, tvb, offset, 1, ENC_BIG_ENDIAN, &arity);
377 offset++;
379 for (i=0; i<arity; i++) {
380 offset = dissect_etf_type(NULL, pinfo, tvb, offset, tree);
383 return offset;
386 static int dissect_etf_big_ext(tvbuff_t *tvb, packet_info *pinfo, int offset, uint32_t len, proto_tree *tree, const char **value_str) {
387 uint8_t sign;
388 int32_t i;
390 sign = tvb_get_uint8(tvb, offset);
391 offset += 1;
393 if (len <= 8) {
394 uint64_t big_val = 0;
396 switch (len) {
397 case 1: big_val = tvb_get_uint8(tvb, offset); break;
398 case 2: big_val = tvb_get_letohs(tvb, offset); break;
399 case 3: big_val = tvb_get_letoh24(tvb, offset); break;
400 case 4: big_val = tvb_get_letohl(tvb, offset); break;
401 case 5: big_val = tvb_get_letoh40(tvb, offset); break;
402 case 6: big_val = tvb_get_letoh48(tvb, offset); break;
403 case 7: big_val = tvb_get_letoh56(tvb, offset); break;
404 case 8: big_val = tvb_get_letoh64(tvb, offset); break;
406 proto_tree_add_uint64_format_value(tree, hf_erldp_big_ext_int, tvb, offset, len,
407 big_val, "%s%" PRIu64, sign ? "-" : "", big_val);
408 if (value_str)
409 *value_str = wmem_strdup_printf(pinfo->pool, "%s%" PRIu64,
410 sign ? "-" : "", big_val);
411 } if (len < 64) {
412 wmem_strbuf_t *strbuf = wmem_strbuf_new_sized(pinfo->pool, len*1+3+1);
414 wmem_strbuf_append(strbuf, "0x");
415 for (i = len - 1; i >= 0; i--) {
416 wmem_strbuf_append_printf(strbuf, "%02x", tvb_get_uint8(tvb, offset + i));
418 char *buf = wmem_strbuf_finalize(strbuf);
420 proto_tree_add_string_format_value(tree, hf_erldp_big_ext_str, tvb, offset, len, buf, "%s", buf);
422 if (value_str)
423 *value_str = buf;
424 } else
425 proto_tree_add_item(tree, hf_erldp_big_ext_bytes, tvb, offset, len, ENC_NA);
427 return offset + len;
430 // NOLINTNEXTLINE(misc-no-recursion)
431 static int dissect_etf_type_content(uint8_t tag, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree, const char **value_str) {
432 int32_t int_val;
433 uint32_t len, i, uint_val;
434 uint32_t id;
435 const uint8_t *str_val;
437 increment_dissection_depth(pinfo);
439 switch (tag) {
440 case ATOM_CACHE_REF:
441 proto_tree_add_item_ret_uint(tree, hf_erldp_atom_cache_ref, tvb, offset, 1, ENC_BIG_ENDIAN, &uint_val);
442 offset += 1;
443 if (value_str)
444 *value_str = wmem_strdup_printf(pinfo->pool, "%d", uint_val);
445 break;
447 case SMALL_INTEGER_EXT:
448 proto_tree_add_item_ret_uint(tree, hf_erldp_small_int_ext, tvb, offset, 1, ENC_BIG_ENDIAN, &uint_val);
449 offset += 1;
450 if (value_str)
451 *value_str = wmem_strdup_printf(pinfo->pool, "%u", uint_val);
452 break;
454 case INTEGER_EXT:
455 proto_tree_add_item_ret_int(tree, hf_erldp_int_ext, tvb, offset, 4, ENC_BIG_ENDIAN, &int_val);
456 offset += 4;
457 if (value_str)
458 *value_str = wmem_strdup_printf(pinfo->pool, "%d", int_val);
459 break;
461 case SMALL_BIG_EXT: {
462 proto_tree_add_item_ret_uint(tree, hf_erldp_small_big_ext_len, tvb, offset, 1, ENC_BIG_ENDIAN, &len);
463 offset += 1;
465 offset = dissect_etf_big_ext(tvb, pinfo, offset, len, tree, value_str);
466 break;
469 case LARGE_BIG_EXT: {
470 proto_tree_add_item_ret_uint(tree, hf_erldp_large_big_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
471 offset += 4;
473 offset = dissect_etf_big_ext(tvb, pinfo, offset, len, tree, value_str);
474 break;
477 case FLOAT_EXT:
478 proto_tree_add_item_ret_string(tree, hf_erldp_float_ext, tvb, offset, 31, ENC_NA|ENC_UTF_8, pinfo->pool, &str_val);
479 offset += 31;
480 if (value_str)
481 *value_str = (const char *)str_val;
482 break;
484 case NEW_FLOAT_EXT:
485 proto_tree_add_item(tree, hf_erldp_new_float_ext, tvb, offset, 8, ENC_BIG_ENDIAN);
486 if (value_str) {
487 double new_float_val = tvb_get_ntohieee_double(tvb, offset);
488 *value_str = wmem_strdup_printf(pinfo->pool, "%f", new_float_val);
490 offset += 8;
491 break;
493 case ATOM_UTF8_EXT:
494 proto_tree_add_item_ret_uint(tree, hf_erldp_atom_length2, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
495 offset += 2;
496 proto_tree_add_item_ret_string(tree, hf_erldp_atom_text, tvb, offset, len, ENC_NA|ENC_UTF_8, pinfo->pool, &str_val);
497 offset += len;
498 if (value_str)
499 *value_str = (const char *)str_val;
500 break;
502 case SMALL_ATOM_UTF8_EXT:
503 proto_tree_add_item_ret_uint(tree, hf_erldp_atom_length, tvb, offset, 1, ENC_BIG_ENDIAN, &len);
504 offset++;
505 proto_tree_add_item_ret_string(tree, hf_erldp_atom_text, tvb, offset, len, ENC_NA|ENC_UTF_8, pinfo->pool, &str_val);
506 offset += len;
507 if (value_str)
508 *value_str = (const char *)str_val;
509 break;
511 case STRING_EXT:
512 proto_tree_add_item_ret_uint(tree, hf_erldp_string_ext_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
513 offset += 2;
514 proto_tree_add_item_ret_string(tree, hf_erldp_string_ext, tvb, offset, len, ENC_NA|ENC_UTF_8, pinfo->pool, &str_val);
515 offset += len;
516 if (value_str)
517 *value_str = (const char *)str_val;
518 break;
520 case PORT_EXT:
521 offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
522 proto_tree_add_item(tree, hf_erldp_port_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
523 offset += 4;
524 proto_tree_add_item(tree, hf_erldp_port_ext_creation, tvb, offset, 1, ENC_BIG_ENDIAN);
525 offset++;
526 break;
528 case NEW_PORT_EXT:
529 offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
530 proto_tree_add_item(tree, hf_erldp_port_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
531 offset += 4;
532 proto_tree_add_item(tree, hf_erldp_port_ext_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
533 offset += 4;
534 break;
536 case V4_PORT_EXT:
537 offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
538 proto_tree_add_item(tree, hf_erldp_port_ext_v4_id, tvb, offset, 8, ENC_BIG_ENDIAN);
539 offset += 8;
540 proto_tree_add_item(tree, hf_erldp_port_ext_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
541 offset += 4;
542 break;
544 case PID_EXT:
545 offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
546 proto_tree_add_item(tree, hf_erldp_pid_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
547 offset += 4;
548 proto_tree_add_item(tree, hf_erldp_pid_ext_serial, tvb, offset, 4, ENC_BIG_ENDIAN);
549 offset += 4;
550 proto_tree_add_item(tree, hf_erldp_pid_ext_creation, tvb, offset, 1, ENC_BIG_ENDIAN);
551 offset++;
552 break;
554 case NEW_PID_EXT:
555 offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
556 proto_tree_add_item(tree, hf_erldp_pid_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
557 offset += 4;
558 proto_tree_add_item(tree, hf_erldp_pid_ext_serial, tvb, offset, 4, ENC_BIG_ENDIAN);
559 offset += 4;
560 proto_tree_add_item(tree, hf_erldp_pid_ext_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
561 offset += 4;
562 break;
564 case SMALL_TUPLE_EXT:
565 offset = dissect_etf_tuple_content(false, pinfo, tvb, offset, tree, value_str);
566 break;
568 case LARGE_TUPLE_EXT:
569 offset = dissect_etf_tuple_content(true, pinfo, tvb, offset, tree, value_str);
570 break;
572 case NIL_EXT:
573 break;
575 case LIST_EXT:
576 proto_tree_add_item_ret_uint(tree, hf_erldp_list_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
577 offset += 4;
578 for (i=0; i<len; i++) {
579 offset = dissect_etf_type(NULL, pinfo, tvb, offset, tree);
581 offset = dissect_etf_type("Tail", pinfo, tvb, offset, tree);
582 break;
584 case MAP_EXT:
585 proto_tree_add_item_ret_uint(tree, hf_erldp_map_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
586 offset += 4;
587 for (i=0; i<len; i++) {
588 // key
589 offset = dissect_etf_type(NULL, pinfo, tvb, offset, tree);
590 // value
591 offset = dissect_etf_type(NULL, pinfo, tvb, offset, tree);
593 break;
595 case BINARY_EXT:
596 proto_tree_add_item_ret_uint(tree, hf_erldp_binary_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
597 offset += 4;
598 proto_tree_add_item(tree, hf_erldp_binary_ext, tvb, offset, len, ENC_NA);
599 offset += len;
600 break;
602 case BIT_BINARY_EXT:
603 proto_tree_add_item_ret_uint(tree, hf_erldp_binary_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
604 offset += 4;
605 proto_tree_add_item(tree, hf_erldp_binary_ext_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
606 offset++;
607 proto_tree_add_item(tree, hf_erldp_binary_ext, tvb, offset, len, ENC_NA);
608 offset += len;
609 break;
611 case NEW_REFERENCE_EXT:
612 proto_tree_add_item_ret_uint(tree, hf_erldp_new_ref_ext_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
613 offset += 2;
614 offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
615 proto_tree_add_item(tree, hf_erldp_new_ref_ext_creation, tvb, offset, 1, ENC_BIG_ENDIAN);
616 offset++;
617 for (i=0; i<len; i++) {
618 id = tvb_get_ntohl(tvb, offset);
619 proto_tree_add_uint_format(tree, hf_erldp_new_ref_ext_id, tvb, offset, 4,
620 id, "ID[%d]: 0x%08X", i, id);
621 offset += 4;
623 break;
625 case NEWER_REFERENCE_EXT:
626 proto_tree_add_item_ret_uint(tree, hf_erldp_new_ref_ext_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
627 offset += 2;
628 offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
629 proto_tree_add_item(tree, hf_erldp_new_ref_ext_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
630 offset += 4;
631 for (i=0; i<len; i++) {
632 id = tvb_get_ntohl(tvb, offset);
633 proto_tree_add_uint_format(tree, hf_erldp_new_ref_ext_id, tvb, offset, 4,
634 id, "ID[%d]: 0x%08X", i, id);
635 offset += 4;
637 break;
639 case FUN_EXT:
640 proto_tree_add_item_ret_uint(tree, hf_erldp_fun_ext_num_free, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
641 offset += 4;
642 offset = dissect_etf_type("Pid", pinfo, tvb, offset, tree);
643 offset = dissect_etf_type("Module", pinfo, tvb, offset, tree);
644 offset = dissect_etf_type("Index", pinfo, tvb, offset, tree);
645 offset = dissect_etf_type("Unique", pinfo, tvb, offset, tree);
647 for (i = 0; i < len; i++) {
648 char buf[ITEM_LABEL_LENGTH];
649 snprintf(buf, sizeof(buf), "Free Var[%u]", i + 1);
650 offset = dissect_etf_type(buf, pinfo, tvb, offset, tree);
652 break;
654 case NEW_FUN_EXT:
655 proto_tree_add_item(tree, hf_erldp_new_fun_ext_size, tvb, offset, 4, ENC_BIG_ENDIAN);
656 offset += 4;
657 proto_tree_add_item(tree, hf_erldp_new_fun_ext_arity, tvb, offset, 1, ENC_BIG_ENDIAN);
658 offset += 1;
659 proto_tree_add_item(tree, hf_erldp_new_fun_ext_uniq, tvb, offset, 16, ENC_NA);
660 offset += 16;
661 proto_tree_add_item(tree, hf_erldp_new_fun_ext_index, tvb, offset, 4, ENC_BIG_ENDIAN);
662 offset += 4;
663 proto_tree_add_item_ret_uint(tree, hf_erldp_new_fun_ext_num_free, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
664 offset += 4;
665 offset = dissect_etf_type("Module", pinfo, tvb, offset, tree);
666 offset = dissect_etf_type("OldIndex", pinfo, tvb, offset, tree);
667 offset = dissect_etf_type("OldUnique", pinfo, tvb, offset, tree);
668 offset = dissect_etf_type("Pid", pinfo, tvb, offset, tree);
670 for (i = 0; i < len; i++) {
671 char buf[ITEM_LABEL_LENGTH];
672 snprintf(buf, sizeof(buf), "Free Var[%u]", i + 1);
673 offset = dissect_etf_type(buf, pinfo, tvb, offset, tree);
675 break;
677 case EXPORT_EXT:
678 offset = dissect_etf_type("Module", pinfo, tvb, offset, tree);
679 offset = dissect_etf_type("Function", pinfo, tvb, offset, tree);
680 offset = dissect_etf_type("Arity", pinfo, tvb, offset, tree);
681 break;
684 decrement_dissection_depth(pinfo);
686 return offset;
689 static int dissect_etf_pdu_data(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree) {
690 uint8_t ctl_op;
692 if ((tvb_get_uint8(tvb, offset) == SMALL_TUPLE_EXT) && (tvb_get_uint8(tvb, offset + 2) == SMALL_INTEGER_EXT)) {
693 ctl_op = tvb_get_uint8(tvb, offset + 3);
694 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(ctl_op, VALS(erldp_ctlmsg_vals), "unknown ControlMessage operation (%d)"));
696 offset = dissect_etf_type("ControlMessage", pinfo, tvb, offset, tree);
697 if (tvb_reported_length_remaining(tvb, offset) > 0)
698 offset = dissect_etf_type("Message", pinfo, tvb, offset, tree);
700 return offset;
703 static int dissect_etf_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const char *label) {
704 int offset = 0;
705 uint8_t mag;
706 uint32_t tag;
707 proto_item *ti;
708 proto_tree *etf_tree;
710 mag = tvb_get_uint8(tvb, offset);
711 if (mag != VERSION_MAGIC) {
712 return 0;
715 etf_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_etf, &ti, (label) ? label : "External Term Format");
717 proto_tree_add_item(etf_tree, hf_etf_version_magic, tvb, offset, 1, ENC_BIG_ENDIAN);
718 offset++;
720 proto_tree_add_item_ret_uint(etf_tree, hf_etf_dist_header_tag, tvb, offset, 1, ENC_BIG_ENDIAN, &tag);
721 offset++;
723 if (!label)
724 proto_item_set_text(ti, "%s", val_to_str(tag, VALS(etf_header_tag_vals), "unknown tag (%d)"));
726 switch (tag) {
727 case DIST_HEADER:
728 offset = dissect_etf_dist_header(pinfo, tvb, offset, etf_tree);
729 proto_item_set_len(ti, offset);
731 dissect_etf_pdu_data(pinfo, tvb, offset, tree);
732 break;
734 case DIST_FRAG_HEADER:
735 case DIST_FRAG_CONT:
737 uint64_t sequence_id, fragment_id;
738 bool save_fragmented;
739 fragment_head *frag_msg = NULL;
740 tvbuff_t *next_tvb = NULL;
741 int len_rem;
743 proto_tree_add_item_ret_uint64(etf_tree, hf_erldp_sequence_id, tvb, offset, 8, ENC_BIG_ENDIAN, &sequence_id);
744 offset += 8;
746 proto_tree_add_item_ret_uint64(etf_tree, hf_erldp_fragment_id, tvb, offset, 8, ENC_BIG_ENDIAN, &fragment_id);
747 offset += 8;
749 save_fragmented = pinfo->fragmented;
751 len_rem = tvb_reported_length_remaining(tvb, offset);
752 if (len_rem <= 0)
753 return offset;
755 pinfo->fragmented = true;
757 frag_msg = fragment_add_seq_next(&erldp_reassembly_table,
758 tvb, offset, pinfo, (uint32_t)sequence_id, NULL,
759 len_rem, fragment_id != 1);
761 next_tvb = process_reassembled_data(tvb, offset, pinfo,
762 "Reassembled ErlDP", frag_msg,
763 &etf_frag_items, NULL, tree);
765 if (next_tvb == NULL)
766 { /* make a new subset */
767 next_tvb = tvb_new_subset_remaining(tvb, offset);
768 call_data_dissector(next_tvb, pinfo, tree);
769 col_append_fstr(pinfo->cinfo, COL_INFO, " (Fragment ID: %" PRIu64 ")", fragment_id);
771 else
773 offset = dissect_etf_dist_header(pinfo, next_tvb, 0, etf_tree);
774 proto_item_set_len(ti, offset);
776 dissect_etf_pdu_data(pinfo, next_tvb, offset, tree);
777 col_append_fstr(pinfo->cinfo, COL_INFO, " (Reassembled, Fragment ID: %" PRIu64 ")", fragment_id);
780 pinfo->fragmented = save_fragmented;
781 offset = tvb_reported_length_remaining(tvb, offset);
782 break;
786 return offset;
789 static int dissect_etf_versioned_type(const char *label, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree) {
790 if (tvb_get_uint8(tvb, offset) != VERSION_MAGIC) {
791 proto_tree_add_item(tree, hf_erldp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
792 col_set_str(pinfo->cinfo, COL_INFO, "unknown header format");
793 return offset + 1;
795 offset += 1;
797 return dissect_etf_type(label, pinfo, tvb, offset, tree);
800 // NOLINTNEXTLINE(misc-no-recursion)
801 static int dissect_etf_type(const char *label, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree) {
802 int begin = offset;
803 uint32_t tag;
804 proto_item *ti;
805 proto_tree *etf_tree;
806 const char *value_str = NULL;
808 etf_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_etf, &ti, (label) ? label : "External Term Format");
810 proto_tree_add_item_ret_uint(etf_tree, hf_etf_tag, tvb, offset, 1, ENC_BIG_ENDIAN, &tag);
811 offset++;
813 if (!label)
814 proto_item_set_text(ti, "%s", val_to_str(tag, VALS(etf_tag_vals), "unknown tag (%d)"));
816 offset = dissect_etf_type_content(tag, pinfo, tvb, offset, etf_tree, &value_str);
817 if (value_str)
818 proto_item_append_text(ti, ": %s", value_str);
820 proto_item_set_len(ti, offset - begin);
822 return offset;
825 static bool is_handshake(tvbuff_t *tvb, int offset) {
826 uint32_t len = tvb_get_ntohs(tvb, offset);
827 uint8_t tag = tvb_get_uint8(tvb, offset + 2);
828 return ((len > 0) && strchr("nNras", tag) && (len == (uint32_t)tvb_captured_length_remaining(tvb, offset + 2)));
831 /*--- dissect_erldp_handshake -------------------------------------------------*/
832 static void dissect_erldp_handshake(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
833 int offset = 0;
834 uint32_t tag;
835 bool is_challenge = false;
836 uint32_t str_len;
837 const uint8_t *str;
839 static int * const erldp_flags_flags[] = {
840 &hf_erldp_flags_spare,
841 &hf_erldp_flags_alias,
842 &hf_erldp_flags_v4_nc,
843 &hf_erldp_flags_name_me,
844 &hf_erldp_flags_spawn,
845 &hf_erldp_flags_reserved,
846 &hf_erldp_flags_unlink_id,
847 &hf_erldp_flags_handshake_23,
848 &hf_erldp_flags_fragments,
849 &hf_erldp_flags_exit_payload,
850 &hf_erldp_flags_pending_connect,
851 &hf_erldp_flags_big_seqtrace_labels,
852 &hf_erldp_flags_send_sender,
853 &hf_erldp_flags_big_creation,
854 &hf_erldp_flags_map_tag,
855 &hf_erldp_flags_utf8_atoms,
856 &hf_erldp_flags_ets_compressed,
857 &hf_erldp_flags_small_atom_tags,
858 &hf_erldp_flags_dist_hdr_atom_cache,
859 &hf_erldp_flags_unicode_io,
860 &hf_erldp_flags_new_floats,
861 &hf_erldp_flags_bit_binaries,
862 &hf_erldp_flags_export_ptr_tag,
863 &hf_erldp_flags_extended_pids_ports,
864 &hf_erldp_flags_new_fun_tags,
865 &hf_erldp_flags_hidden_atom_cache,
866 &hf_erldp_flags_dist_monitor_name,
867 &hf_erldp_flags_fun_tags,
868 &hf_erldp_flags_dist_monitor,
869 &hf_erldp_flags_extended_references,
870 &hf_erldp_flags_atom_cache,
871 &hf_erldp_flags_published,
872 NULL
875 proto_tree_add_item(tree, hf_erldp_length_2, tvb, offset, 2, ENC_BIG_ENDIAN);
876 offset += 2;
877 proto_tree_add_item_ret_uint(tree, hf_erldp_tag, tvb, offset, 1, ENC_ASCII|ENC_NA, &tag);
878 offset++;
880 switch (tag) {
881 case 'n' :
882 proto_tree_add_item(tree, hf_erldp_version, tvb, offset, 2, ENC_BIG_ENDIAN);
883 offset += 2;
885 proto_tree_add_bitmask(tree, tvb, offset, hf_erldp_flags_v5,
886 ett_erldp_flags, erldp_flags_flags, ENC_BIG_ENDIAN);
887 offset += 4;
888 if (tvb_bytes_exist(tvb, offset, 4)) {
889 if (!tvb_ascii_isprint(tvb, offset, 4)) {
890 is_challenge = true;
893 if (is_challenge) {
894 proto_tree_add_item(tree, hf_erldp_challenge, tvb, offset, 4, ENC_BIG_ENDIAN);
895 offset += 4;
897 str_len = tvb_captured_length_remaining(tvb, offset);
898 proto_tree_add_item_ret_string(tree, hf_erldp_name, tvb, offset, str_len, ENC_ASCII|ENC_NA, pinfo->pool, &str);
899 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", (is_challenge) ? "SEND_CHALLENGE" : "SEND_NAME", str);
900 break;
902 case 'N':
903 proto_tree_add_bitmask(tree, tvb, offset, hf_erldp_flags_v6,
904 ett_erldp_flags, erldp_flags_flags, ENC_BIG_ENDIAN);
905 offset += 8;
906 if (tvb_bytes_exist(tvb, offset + 6, 4)) {
907 if (!tvb_ascii_isprint(tvb, offset + 6, 4)) {
908 is_challenge = true;
911 if (is_challenge) {
912 proto_tree_add_item(tree, hf_erldp_challenge, tvb, offset, 4, ENC_BIG_ENDIAN);
913 offset += 4;
915 proto_tree_add_item(tree, hf_erldp_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
916 offset += 4;
917 proto_tree_add_item_ret_uint(tree, hf_erldp_nlen, tvb, offset, 2, ENC_BIG_ENDIAN, &str_len);
918 offset += 2;
919 proto_tree_add_item_ret_string(tree, hf_erldp_name, tvb, offset, str_len, ENC_ASCII|ENC_NA, pinfo->pool, &str);
920 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", (is_challenge) ? "SEND_CHALLENGE" : "SEND_NAME", str);
921 break;
923 case 'r' :
924 proto_tree_add_item(tree, hf_erldp_challenge, tvb, offset, 4, ENC_BIG_ENDIAN);
925 offset += 4;
926 proto_tree_add_item(tree, hf_erldp_digest, tvb, offset, 16, ENC_NA);
927 /*offset += 16;*/
928 col_set_str(pinfo->cinfo, COL_INFO, "SEND_CHALLENGE_REPLY");
929 break;
931 case 'a' :
932 proto_tree_add_item(tree, hf_erldp_digest, tvb, offset, 16, ENC_NA);
933 /*offset += 16;*/
934 col_set_str(pinfo->cinfo, COL_INFO, "SEND_CHALLENGE_ACK");
935 break;
937 case 's' :
938 str_len = tvb_captured_length_remaining(tvb, offset);
939 proto_tree_add_item_ret_string(tree, hf_erldp_status, tvb, offset, str_len, ENC_ASCII|ENC_NA, pinfo->pool, &str);
940 col_add_fstr(pinfo->cinfo, COL_INFO, "SEND_STATUS %s", str);
941 break;
945 /*--- dissect_erldp_pdu -------------------------------------------------*/
946 static int dissect_erldp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
947 int offset;
948 uint32_t msg_len;
949 uint8_t type;
950 proto_tree *erldp_tree;
951 proto_item *ti;
952 tvbuff_t *next_tvb = NULL;
954 col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
956 ti = proto_tree_add_item(tree, proto_erldp, tvb, 0, -1, ENC_NA);
957 erldp_tree = proto_item_add_subtree(ti, ett_erldp);
959 if (is_handshake(tvb, 0)) {
960 dissect_erldp_handshake(tvb, pinfo, erldp_tree);
961 return tvb_captured_length(tvb);
964 offset = 0;
966 proto_tree_add_item_ret_uint(erldp_tree, hf_erldp_length_4, tvb, offset, 4, ENC_BIG_ENDIAN, &msg_len);
967 offset += 4;
969 if (msg_len == 0) {
970 col_set_str(pinfo->cinfo, COL_INFO, "KEEP_ALIVE");
971 return offset;
974 type = tvb_get_uint8(tvb, offset);
975 switch (type) {
976 case ERL_PASS_THROUGH:
977 proto_tree_add_item(erldp_tree, hf_erldp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
978 offset += 1;
980 offset = dissect_etf_versioned_type("ControlMessage", pinfo, tvb, offset, erldp_tree);
981 if (tvb_reported_length_remaining(tvb, offset) > 0) {
982 dissect_etf_versioned_type("Message", pinfo, tvb, offset, erldp_tree);
984 break;
986 case VERSION_MAGIC:
987 next_tvb = tvb_new_subset_length_caplen(tvb, offset, -1, 4 + msg_len - offset);
988 dissect_etf_pdu(next_tvb, pinfo, erldp_tree, "DistributionHeader");
989 break;
991 default:
992 proto_tree_add_item(erldp_tree, hf_erldp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
993 offset++;
994 col_set_str(pinfo->cinfo, COL_INFO, "unknown header format");
997 return tvb_captured_length(tvb);
1000 /*--- get_erldp_pdu_len -------------------------------------------------*/
1001 static unsigned get_erldp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
1002 int offset, void *data _U_)
1004 if (is_handshake(tvb, offset))
1005 return 2 + tvb_get_ntohs(tvb, offset);
1007 return 4 + tvb_get_ntohl(tvb, offset);
1010 /*--- dissect_erldp -------------------------------------------------*/
1011 static int
1012 dissect_erldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) {
1013 tcp_dissect_pdus(tvb, pinfo, tree,
1014 erldp_desegment, /* desegment or not */
1015 4, /* fixed-length part of the PDU */
1016 get_erldp_pdu_len, /* routine to get the length of the PDU */
1017 dissect_erldp_pdu, data); /* routine to dissect a PDU */
1018 return tvb_captured_length(tvb);
1021 /*--- proto_register_erldp ----------------------------------------------*/
1022 void proto_register_erldp(void) {
1023 /* module_t *erldp_module; */
1025 /* List of fields */
1026 static hf_register_info hf[] = {
1027 /*--- Handshake fields ---*/
1028 { &hf_erldp_length_2, { "Length", "erldp.len",
1029 FT_UINT16, BASE_DEC, NULL, 0x0,
1030 "Message Length", HFILL}},
1031 { &hf_etf_version_magic, { "VERSION_MAGIC", "erldp.version_magic",
1032 FT_UINT8, BASE_DEC, NULL, 0x0,
1033 NULL, HFILL}},
1034 { &hf_erldp_tag, { "Tag", "erldp.tag",
1035 FT_CHAR, BASE_HEX, NULL, 0x0,
1036 NULL, HFILL}},
1037 { &hf_erldp_type, { "Type", "erldp.type",
1038 FT_UINT8, BASE_DEC, NULL, 0x0,
1039 NULL, HFILL}},
1040 { &hf_erldp_version, { "Version", "erldp.version",
1041 FT_UINT16, BASE_DEC, VALS(epmd_version_vals), 0x0,
1042 NULL, HFILL}},
1043 { &hf_erldp_flags_v5, { "Flags", "erldp.flags_v5",
1044 FT_UINT32, BASE_HEX, NULL, 0x0,
1045 NULL, HFILL}},
1046 { &hf_erldp_flags_v6, { "Flags", "erldp.flags_v6",
1047 FT_UINT64, BASE_HEX, NULL, 0x0,
1048 NULL, HFILL}},
1049 { &hf_erldp_flags_published, { "Published", "erldp.flags.published",
1050 FT_BOOLEAN, 64, NULL, 0x1,
1051 NULL, HFILL }},
1052 { &hf_erldp_flags_atom_cache, { "Atom Cache", "erldp.flags.atom_cache",
1053 FT_BOOLEAN, 64, NULL, 0x2,
1054 NULL, HFILL }},
1055 { &hf_erldp_flags_extended_references, { "Extended References", "erldp.flags.extended_references",
1056 FT_BOOLEAN, 64, NULL, 0x4,
1057 NULL, HFILL }},
1058 { &hf_erldp_flags_dist_monitor, { "Dist Monitor", "erldp.flags.dist_monitor",
1059 FT_BOOLEAN, 64, NULL, 0x8,
1060 NULL, HFILL }},
1061 { &hf_erldp_flags_fun_tags, { "Fun Tags", "erldp.flags.fun_tags",
1062 FT_BOOLEAN, 64, NULL, 0x10,
1063 NULL, HFILL }},
1064 { &hf_erldp_flags_dist_monitor_name, { "Dist Monitor Name", "erldp.flags.dist_monitor_name",
1065 FT_BOOLEAN, 64, NULL, 0x20,
1066 NULL, HFILL }},
1067 { &hf_erldp_flags_hidden_atom_cache, { "Hidden Atom Cache", "erldp.flags.hidden_atom_cache",
1068 FT_BOOLEAN, 64, NULL, 0x40,
1069 NULL, HFILL }},
1070 { &hf_erldp_flags_new_fun_tags, { "New Fun Tags", "erldp.flags.new_fun_tags",
1071 FT_BOOLEAN, 64, NULL, 0x80,
1072 NULL, HFILL }},
1073 { &hf_erldp_flags_extended_pids_ports, { "Extended Pids Ports", "erldp.flags.extended_pids_ports",
1074 FT_BOOLEAN, 64, NULL, 0x100,
1075 NULL, HFILL }},
1076 { &hf_erldp_flags_export_ptr_tag, { "Export PTR Tag", "erldp.flags.export_ptr_tag",
1077 FT_BOOLEAN, 64, NULL, 0x200,
1078 NULL, HFILL }},
1079 { &hf_erldp_flags_bit_binaries, { "Bit Binaries", "erldp.flags.bit_binaries",
1080 FT_BOOLEAN, 64, NULL, 0x400,
1081 NULL, HFILL }},
1082 { &hf_erldp_flags_new_floats, { "New Floats", "erldp.flags.new_floats",
1083 FT_BOOLEAN, 64, NULL, 0x800,
1084 NULL, HFILL }},
1085 { &hf_erldp_flags_unicode_io, { "Unicode IO", "erldp.flags.unicode_io",
1086 FT_BOOLEAN, 64, NULL, 0x1000,
1087 NULL, HFILL }},
1088 { &hf_erldp_flags_dist_hdr_atom_cache, { "Dist HDR Atom Cache", "erldp.flags.dist_hdr_atom_cache",
1089 FT_BOOLEAN, 64, NULL, 0x2000,
1090 NULL, HFILL }},
1091 { &hf_erldp_flags_small_atom_tags, { "Small Atom Tags", "erldp.flags.small_atom_tags",
1092 FT_BOOLEAN, 64, NULL, 0x4000,
1093 NULL, HFILL }},
1094 { &hf_erldp_flags_ets_compressed, { "ETS Compressed", "erldp.flags.ets_compressed",
1095 FT_BOOLEAN, 64, NULL, 0x8000,
1096 NULL, HFILL }},
1097 { &hf_erldp_flags_utf8_atoms, { "UTF8 Atoms", "erldp.flags.utf8_atoms",
1098 FT_BOOLEAN, 64, NULL, 0x10000,
1099 NULL, HFILL }},
1100 { &hf_erldp_flags_map_tag, { "Map Tag", "erldp.flags.map_tag",
1101 FT_BOOLEAN, 64, NULL, 0x20000,
1102 NULL, HFILL }},
1103 { &hf_erldp_flags_big_creation, { "Big Creation", "erldp.flags.big_creation",
1104 FT_BOOLEAN, 64, NULL, 0x40000,
1105 NULL, HFILL }},
1106 { &hf_erldp_flags_send_sender, { "Send Sender", "erldp.flags.send_sender",
1107 FT_BOOLEAN, 64, NULL, 0x80000,
1108 NULL, HFILL }},
1109 { &hf_erldp_flags_big_seqtrace_labels, { "Big Seqtrace Labels", "erldp.flags.big_seqtrace_labels",
1110 FT_BOOLEAN, 64, NULL, 0x100000,
1111 NULL, HFILL }},
1112 { &hf_erldp_flags_pending_connect, { "Pending Connect", "erldp.flags.pending_connect",
1113 FT_BOOLEAN, 64, NULL, 0x200000,
1114 NULL, HFILL }},
1115 { &hf_erldp_flags_exit_payload, { "Exit Payload", "erldp.flags.exit_payload",
1116 FT_BOOLEAN, 64, NULL, 0x400000,
1117 NULL, HFILL }},
1118 { &hf_erldp_flags_fragments, { "Fragments", "erldp.flags.fragments",
1119 FT_BOOLEAN, 64, NULL, 0x800000,
1120 NULL, HFILL }},
1121 { &hf_erldp_flags_handshake_23, { "Handshake 23", "erldp.flags.handshake_23",
1122 FT_BOOLEAN, 64, NULL, 0x1000000,
1123 NULL, HFILL }},
1124 { &hf_erldp_flags_unlink_id, { "Unlink Id", "erldp.flags.unlink_id",
1125 FT_BOOLEAN, 64, NULL, 0x2000000,
1126 NULL, HFILL }},
1127 { &hf_erldp_flags_reserved, { "Reserved", "erldp.flags.reserved",
1128 FT_UINT64, BASE_DEC, NULL, 0xfc000000,
1129 NULL, HFILL }},
1130 { &hf_erldp_flags_spawn, { "Spawn", "erldp.flags.spawn",
1131 FT_BOOLEAN, 64, NULL, 1ULL << 32,
1132 NULL, HFILL }},
1133 { &hf_erldp_flags_name_me, { "Name ME", "erldp.flags.name_me",
1134 FT_BOOLEAN, 64, NULL, 1ULL << 33,
1135 NULL, HFILL }},
1136 { &hf_erldp_flags_v4_nc, { "V4 NC", "erldp.flags.v4_nc",
1137 FT_BOOLEAN, 64, NULL, 1ULL << 34,
1138 NULL, HFILL }},
1139 { &hf_erldp_flags_alias, { "Alias", "erldp.flags.alias",
1140 FT_BOOLEAN, 64, NULL, 1ULL << 35,
1141 NULL, HFILL }},
1142 { &hf_erldp_flags_spare, { "Spare", "erldp.flags.spare",
1143 FT_UINT64, BASE_DEC, NULL, ~(0ULL) << 36,
1144 NULL, HFILL }},
1145 { &hf_erldp_creation, { "Creation", "erldp.creation",
1146 FT_UINT32, BASE_DEC, NULL, 0x0,
1147 NULL, HFILL}},
1148 { &hf_erldp_challenge, { "Challenge", "erldp.challenge",
1149 FT_UINT32, BASE_HEX, NULL, 0x0,
1150 NULL, HFILL}},
1151 { &hf_erldp_digest, { "Digest", "erldp.digest",
1152 FT_BYTES, BASE_NONE, NULL, 0x0,
1153 NULL, HFILL}},
1154 { &hf_erldp_nlen, { "Name Length", "erldp.nlen",
1155 FT_UINT16, BASE_DEC, NULL, 0x0,
1156 NULL, HFILL}},
1157 { &hf_erldp_name, { "Name", "erldp.name",
1158 FT_STRING, BASE_NONE, NULL, 0x0,
1159 NULL, HFILL}},
1160 { &hf_erldp_status, { "Status", "erldp.status",
1161 FT_STRING, BASE_NONE, NULL, 0x0,
1162 NULL, HFILL}},
1163 { &hf_erldp_sequence_id, { "Sequence Id", "erldp.sequence_id",
1164 FT_UINT64, BASE_HEX, NULL, 0x0,
1165 NULL, HFILL}},
1166 { &hf_erldp_fragment_id, { "Fragment Id", "erldp.fragment_id",
1167 FT_UINT64, BASE_HEX, NULL, 0x0,
1168 NULL, HFILL}},
1169 { &hf_erldp_num_atom_cache_refs, { "NumberOfAtomCacheRefs", "erldp.num_atom_cache_refs",
1170 FT_UINT8, BASE_DEC, NULL, 0x0,
1171 NULL, HFILL}},
1172 { &hf_erldp_etf_flags, { "Flags", "erldp.etf_flags",
1173 FT_BYTES, BASE_NONE, NULL, 0x0,
1174 NULL, HFILL}},
1175 { &hf_erldp_internal_segment_index, { "InternalSegmentIndex", "erldp.internal_segment_index",
1176 FT_UINT8, BASE_DEC, NULL, 0x0,
1177 NULL, HFILL}},
1178 { &hf_erldp_atom_length, { "Length", "erldp.atom_length",
1179 FT_UINT8, BASE_DEC, NULL, 0x0,
1180 NULL, HFILL}},
1181 { &hf_erldp_atom_length2, { "Length", "erldp.atom_length",
1182 FT_UINT16, BASE_DEC, NULL, 0x0,
1183 NULL, HFILL}},
1184 { &hf_erldp_atom_text, { "AtomText", "erldp.atom_text",
1185 FT_STRING, BASE_NONE, NULL, 0x0,
1186 NULL, HFILL}},
1187 { &hf_erldp_string_ext_len, { "Len", "erldp.string_ext_len",
1188 FT_UINT16, BASE_DEC, NULL, 0x0,
1189 NULL, HFILL}},
1190 { &hf_erldp_string_ext, { "String", "erldp.string_ext",
1191 FT_STRING, BASE_SHOW_ASCII_PRINTABLE, NULL, 0x0,
1192 NULL, HFILL}},
1193 { &hf_erldp_atom_cache_ref, { "AtomCacheReferenceIndex", "erldp.atom_cache_ref",
1194 FT_UINT8, BASE_DEC, NULL, 0x0,
1195 NULL, HFILL}},
1196 { &hf_erldp_small_int_ext, { "Int", "erldp.small_int_ext",
1197 FT_UINT8, BASE_DEC, NULL, 0x0,
1198 NULL, HFILL}},
1199 { &hf_erldp_int_ext, { "Int", "erldp.int_ext",
1200 FT_INT32, BASE_DEC, NULL, 0x0,
1201 NULL, HFILL}},
1202 { &hf_erldp_small_big_ext_len, { "Len", "erldp.small_big_ext_len",
1203 FT_UINT8, BASE_DEC, NULL, 0x0,
1204 NULL, HFILL}},
1205 { &hf_erldp_large_big_ext_len, { "Len", "erldp.large_big_ext_len",
1206 FT_UINT32, BASE_DEC, NULL, 0x0,
1207 NULL, HFILL}},
1208 { &hf_erldp_big_ext_int, { "Int", "erldp.big_ext_int",
1209 FT_UINT64, BASE_DEC, NULL, 0x0,
1210 NULL, HFILL}},
1211 { &hf_erldp_big_ext_str, { "Int", "erldp.big_ext_str",
1212 FT_STRING, BASE_NONE, NULL, 0x0,
1213 NULL, HFILL}},
1214 { &hf_erldp_big_ext_bytes, { "Int", "erldp.big_ext_bytes",
1215 FT_BYTES, BASE_NONE, NULL, 0x0,
1216 NULL, HFILL}},
1217 { &hf_erldp_float_ext, { "Float", "erldp.float_ext",
1218 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1219 NULL, HFILL}},
1220 { &hf_erldp_new_float_ext, { "Float", "erldp.new_float_ext",
1221 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1222 NULL, HFILL}},
1223 { &hf_erldp_port_ext_id, { "ID", "erldp.port_ext.id",
1224 FT_UINT32, BASE_HEX, NULL, 0x0,
1225 NULL, HFILL}},
1226 { &hf_erldp_port_ext_v4_id, { "ID", "erldp.port_ext.v4_id",
1227 FT_UINT64, BASE_HEX, NULL, 0x0,
1228 NULL, HFILL}},
1229 { &hf_erldp_port_ext_creation, { "Creation", "erldp.port_ext.creation",
1230 FT_UINT32, BASE_DEC, NULL, 0x0,
1231 NULL, HFILL}},
1232 { &hf_erldp_pid_ext_id, { "ID", "erldp.pid_ext.id",
1233 FT_UINT32, BASE_HEX, NULL, 0x0,
1234 NULL, HFILL}},
1235 { &hf_erldp_pid_ext_serial, { "Serial", "erldp.pid_ext.serial",
1236 FT_UINT32, BASE_DEC, NULL, 0x0,
1237 NULL, HFILL}},
1238 { &hf_erldp_pid_ext_creation, { "Creation", "erldp.pid_ext.creation",
1239 FT_UINT32, BASE_DEC, NULL, 0x0,
1240 NULL, HFILL}},
1241 { &hf_erldp_list_ext_len, { "Len", "erldp.list_ext.len",
1242 FT_UINT32, BASE_DEC, NULL, 0x0,
1243 NULL, HFILL}},
1244 { &hf_erldp_map_ext_len, { "Len", "erldp.map_ext.len",
1245 FT_UINT32, BASE_DEC, NULL, 0x0,
1246 NULL, HFILL}},
1247 { &hf_erldp_binary_ext_len, { "Len", "erldp.binary_ext.len",
1248 FT_UINT32, BASE_DEC, NULL, 0x0,
1249 NULL, HFILL}},
1250 { &hf_erldp_binary_ext_bits, { "Num bits in last byte", "erldp.binary_ext.bits",
1251 FT_UINT8, BASE_DEC, NULL, 0x0,
1252 NULL, HFILL}},
1253 { &hf_erldp_binary_ext, { "Binary", "erldp.binary_ext",
1254 FT_BYTES, BASE_SHOW_ASCII_PRINTABLE, NULL, 0x0,
1255 NULL, HFILL}},
1256 { &hf_erldp_new_ref_ext_len, { "Len", "erldp.new_ref_ext.len",
1257 FT_UINT16, BASE_DEC, NULL, 0x0,
1258 NULL, HFILL}},
1259 { &hf_erldp_new_ref_ext_creation, { "Creation", "erldp.new_ref_ext.creation",
1260 FT_UINT32, BASE_DEC, NULL, 0x0,
1261 NULL, HFILL}},
1262 { &hf_erldp_new_ref_ext_id, { "ID", "erldp.new_ref_ext.id",
1263 FT_UINT32, BASE_HEX, NULL, 0x0,
1264 NULL, HFILL}},
1265 { &hf_erldp_fun_ext_num_free, { "Num Free", "erldp.fun_ext.num_free",
1266 FT_UINT32, BASE_DEC, NULL, 0x0,
1267 NULL, HFILL}},
1268 { &hf_erldp_new_fun_ext_size, { "Size", "erldp.new_fun_ext.size",
1269 FT_UINT32, BASE_DEC, NULL, 0x0,
1270 NULL, HFILL}},
1271 { &hf_erldp_new_fun_ext_arity, { "Arity", "erldp.new_fun_ext.arity",
1272 FT_UINT8, BASE_DEC, NULL, 0x0,
1273 NULL, HFILL}},
1274 { &hf_erldp_new_fun_ext_uniq, { "Uniq", "erldp.new_fun_ext.uniq",
1275 FT_BYTES, BASE_NONE, NULL, 0x0,
1276 NULL, HFILL}},
1277 { &hf_erldp_new_fun_ext_index, { "Index", "erldp.new_fun_ext.index",
1278 FT_UINT32, BASE_DEC, NULL, 0x0,
1279 NULL, HFILL}},
1280 { &hf_erldp_new_fun_ext_num_free, { "Num Free", "erldp.new_fun_ext.num_free",
1281 FT_UINT32, BASE_DEC, NULL, 0x0,
1282 NULL, HFILL}},
1284 /*--- ---*/
1285 { &hf_erldp_length_4, { "Length", "erldp.len",
1286 FT_UINT32, BASE_DEC, NULL, 0x0,
1287 "Message Length", HFILL}},
1289 /*--- ETF ---*/
1290 { &hf_etf_tag, { "Tag", "erldp.etf_tag",
1291 FT_UINT8, BASE_DEC, VALS(etf_tag_vals), 0x0,
1292 NULL, HFILL}},
1293 { &hf_etf_dist_header_tag, { "Tag", "erldp.etf_header_tag",
1294 FT_UINT8, BASE_DEC, VALS(etf_header_tag_vals), 0x0,
1295 NULL, HFILL}},
1297 { &hf_etf_dist_header_new_cache, { "NewCacheEntryFlag", "erldp.dist_header.new_cache",
1298 FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x08,
1299 NULL, HFILL}},
1301 { &hf_etf_dist_header_segment_index, { "SegmentIndex", "erldp.dist_header.segment_index",
1302 FT_UINT8, BASE_DEC, NULL, 0x7,
1303 NULL, HFILL}},
1305 { &hf_etf_dist_header_long_atoms, { "LongAtoms", "erldp.dist_header.long_atoms",
1306 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x12,
1307 NULL, HFILL}},
1309 { &hf_etf_arity4, { "Arity", "erldp.arity",
1310 FT_UINT32, BASE_DEC, NULL, 0x0,
1311 NULL, HFILL}},
1313 { &hf_etf_arity, { "Arity", "erldp.arity",
1314 FT_UINT8, BASE_DEC, NULL, 0x0,
1315 NULL, HFILL}},
1317 { &hf_etf_fragments, { "Message fragments", "erldp.dist.fragments",
1318 FT_NONE, BASE_NONE, NULL, 0x0, NULL,
1319 HFILL }},
1321 { &hf_etf_fragment, { "Message fragment", "erldp.dist.fragment",
1322 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1323 NULL, HFILL }},
1325 { &hf_etf_fragment_overlap, { "Message fragment overlap", "erldp.dist.fragment.overlap",
1326 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1327 NULL, HFILL }},
1329 { &hf_etf_fragment_overlap_conflicts, { "Message fragment overlapping with conflicting data",
1330 "erldp.dist.fragment.overlap.conflicts",
1331 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1332 NULL, HFILL }},
1334 { &hf_etf_fragment_multiple_tails, { "Message has multiple tail fragments",
1335 "erldp.dist.fragment.multiple_tails",
1336 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1337 NULL, HFILL }},
1339 { &hf_etf_fragment_too_long_fragment, { "Message fragment too long", "erldp.dist.fragment.too_long_fragment",
1340 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1341 NULL, HFILL }},
1343 { &hf_etf_fragment_error, { "Message defragmentation error", "erldp.dist.fragment.error",
1344 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1345 NULL, HFILL }},
1347 { &hf_etf_fragment_count, { "Message fragment count", "erldp.dist.fragment.count",
1348 FT_UINT32, BASE_DEC, NULL, 0x0,
1349 NULL, HFILL }},
1351 { &hf_etf_reassembled_in, { "Reassembled in", "erldp.dist.reassembled.in",
1352 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1353 NULL, HFILL }},
1355 { &hf_etf_reassembled_length, { "Reassembled length", "erldp.dist.reassembled.length",
1356 FT_UINT32, BASE_DEC, NULL, 0x0,
1357 NULL, HFILL }},
1359 { &hf_etf_reassembled_data, { "Reassembled data", "erldp.dist.reassembled.data",
1360 FT_BYTES, BASE_NONE, NULL, 0x0,
1361 NULL, HFILL }},
1364 /* List of subtrees */
1365 static int *ett[] = {
1366 &ett_erldp,
1367 &ett_erldp_flags,
1368 &ett_etf,
1369 &ett_etf_flags,
1370 &ett_etf_acrs,
1371 &ett_etf_acr,
1372 &ett_etf_tmp,
1373 &ett_etf_fragment,
1374 &ett_etf_fragments,
1377 /* Register protocol and dissector */
1378 proto_erldp = proto_register_protocol(PNAME, PSNAME, PFNAME);
1379 reassembly_table_register(&erldp_reassembly_table,
1380 &addresses_reassembly_table_functions);
1382 erldp_handle = register_dissector(PFNAME, dissect_erldp, proto_erldp);
1384 /* Register fields and subtrees */
1385 proto_register_field_array(proto_erldp, hf, array_length(hf));
1386 proto_register_subtree_array(ett, array_length(ett));
1390 /*--- proto_reg_handoff_erldp -------------------------------------------*/
1391 void proto_reg_handoff_erldp(void) {
1393 dissector_add_for_decode_as_with_preference("tcp.port", erldp_handle);
1397 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1399 * Local Variables:
1400 * c-basic-offset: 2
1401 * tab-width: 8
1402 * indent-tabs-mode: nil
1403 * End:
1405 * ex: set shiftwidth=2 tabstop=8 expandtab:
1406 * :indentSize=2:tabSize=8:noTabs=true: