Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-erldp.c
Line
Count
Source
1
/* packet-erldp.c
2
 * Erlang Distribution Protocol
3
 * http://www.erlang.org/doc/apps/erts/erl_dist_protocol.html
4
 *
5
 * 2010  Tomas Kukosa
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@wireshark.org>
9
 * Copyright 1998 Gerald Combs
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 */
13
14
#include "config.h"
15
16
17
#include <epan/packet.h>
18
#include <epan/expert.h>
19
#include <epan/tfs.h>
20
#include <epan/reassemble.h>
21
#include "packet-tcp.h"
22
#include "packet-epmd.h"
23
24
0
#define ERL_PASS_THROUGH      'p'
25
26
0
#define VERSION_MAGIC 131   /* 130 in erlang 4.2 */
27
28
0
#define SMALL_INTEGER_EXT   'a'
29
0
#define INTEGER_EXT         'b'
30
0
#define FLOAT_EXT           'c'
31
0
#define ATOM_EXT            'd'
32
0
#define ATOM_UTF8_EXT       'v'
33
0
#define SMALL_ATOM_EXT      's'
34
0
#define SMALL_ATOM_UTF8_EXT 'w'
35
0
#define REFERENCE_EXT       'e'
36
0
#define NEW_REFERENCE_EXT   'r'
37
0
#define NEWER_REFERENCE_EXT 'Z'
38
0
#define PORT_EXT            'f'
39
0
#define NEW_PORT_EXT        'Y'
40
0
#define V4_PORT_EXT         'x'
41
0
#define NEW_FLOAT_EXT       'F'
42
0
#define PID_EXT             'g'
43
0
#define NEW_PID_EXT         'X'
44
0
#define SMALL_TUPLE_EXT     'h'
45
0
#define LARGE_TUPLE_EXT     'i'
46
0
#define NIL_EXT             'j'
47
0
#define STRING_EXT          'k'
48
0
#define LIST_EXT            'l'
49
0
#define BINARY_EXT          'm'
50
0
#define BIT_BINARY_EXT      'M'
51
0
#define SMALL_BIG_EXT       'n'
52
0
#define LARGE_BIG_EXT       'o'
53
0
#define NEW_FUN_EXT         'p'
54
0
#define EXPORT_EXT          'q'
55
0
#define FUN_EXT             'u'
56
0
#define MAP_EXT             't'
57
0
#define LOCAL_EXT           'y'
58
0
#define RECORD_EXT          'C'
59
60
0
#define DIST_HEADER         'D'
61
0
#define DIST_FRAG_HEADER    'E'
62
0
#define DIST_FRAG_CONT      'F'
63
0
#define ATOM_CACHE_REF      'R'
64
#define COMPRESSED          'P'
65
66
0
#define DOP_ALTACT_SIG_SEND 37
67
68
16
#define ALTACT_SIG_FLG_PRIO   0x01
69
16
#define ALTACT_SIG_FLG_TOKEN  0x02
70
16
#define ALTACT_SIG_FLG_ALIAS  0x04
71
16
#define ALTACT_SIG_FLG_NAME   0x08
72
16
#define ALTACT_SIG_FLG_EXIT   0x10
73
74
void proto_register_erldp(void);
75
void proto_reg_handoff_erldp(void);
76
77
static const value_string etf_tag_vals[] = {
78
  { SMALL_INTEGER_EXT   , "SMALL_INTEGER_EXT" },
79
  { INTEGER_EXT         , "INTEGER_EXT" },
80
  { FLOAT_EXT           , "FLOAT_EXT" },
81
  { ATOM_EXT            , "ATOM_EXT" },
82
  { ATOM_UTF8_EXT       , "ATOM_UTF8_EXT" },
83
  { SMALL_ATOM_EXT      , "SMALL_ATOM_EXT" },
84
  { SMALL_ATOM_UTF8_EXT , "SMALL_ATOM_UTF8_EXT" },
85
  { REFERENCE_EXT       , "REFERENCE_EXT" },
86
  { NEW_REFERENCE_EXT   , "NEW_REFERENCE_EXT" },
87
  { NEWER_REFERENCE_EXT , "NEWER_REFERENCE_EXT" },
88
  { PORT_EXT            , "PORT_EXT" },
89
  { NEW_PORT_EXT        , "NEW_PORT_EXT" },
90
  { V4_PORT_EXT         , "V4_PORT_EXT" },
91
  { NEW_FLOAT_EXT       , "NEW_FLOAT_EXT" },
92
  { PID_EXT             , "PID_EXT" },
93
  { NEW_PID_EXT         , "NEW_PID_EXT" },
94
  { SMALL_TUPLE_EXT     , "SMALL_TUPLE_EXT" },
95
  { LARGE_TUPLE_EXT     , "LARGE_TUPLE_EXT" },
96
  { NIL_EXT             , "NIL_EXT" },
97
  { STRING_EXT          , "STRING_EXT" },
98
  { LIST_EXT            , "LIST_EXT" },
99
  { BINARY_EXT          , "BINARY_EXT" },
100
  { BIT_BINARY_EXT      , "BIT_BINARY_EXT" },
101
  { SMALL_BIG_EXT       , "SMALL_BIG_EXT" },
102
  { LARGE_BIG_EXT       , "LARGE_BIG_EXT" },
103
  { NEW_FUN_EXT         , "NEW_FUN_EXT" },
104
  { EXPORT_EXT          , "EXPORT_EXT" },
105
  { FUN_EXT             , "FUN_EXT" },
106
  { MAP_EXT             , "MAP_EXT" },
107
  { LOCAL_EXT           , "LOCAL_EXT" },
108
  { RECORD_EXT          , "RECORD_EXT" },
109
  { DIST_HEADER         , "DIST_HEADER" },
110
  { DIST_FRAG_HEADER    , "DIST_FRAG_HEADER" },
111
  { ATOM_CACHE_REF      , "ATOM_CACHE_REF" },
112
  { COMPRESSED          , "COMPRESSED" },
113
  {  0, NULL }
114
};
115
116
static const value_string etf_header_tag_vals[] = {
117
  { DIST_HEADER         , "DIST_HEADER" },
118
  { DIST_FRAG_HEADER    , "DIST_FRAG_HEADER" },
119
  { DIST_FRAG_CONT      , "DIST_FRAG_CONT" },
120
  {  0, NULL }
121
};
122
123
static const value_string erldp_ctlmsg_vals[] = {
124
  {  1, "LINK" },
125
  {  2, "SEND" },
126
  {  3, "EXIT" },
127
  {  4, "UNLINK" },
128
  {  5, "NODE_LINK" },
129
  {  6, "REG_SEND" },
130
  {  7, "GROUP_LEADER" },
131
  {  8, "EXIT2" },
132
  { 12, "SEND_TT" },
133
  { 13, "EXIT_TT" },
134
  { 16, "REG_SEND_TT" },
135
  { 18, "EXIT2_TT" },
136
  { 19, "MONITOR_P" },
137
  { 20, "DEMONITOR_P" },
138
  { 21, "MONITOR_P_EXIT" },
139
  { 22, "SEND_SENDER" },
140
  { 23, "SEND_SENDER_TT" },
141
  { 24, "PAYLOAD_EXIT" },
142
  { 25, "PAYLOAD_EXIT_TT" },
143
  { 26, "PAYLOAD_EXIT2" },
144
  { 27, "PAYLOAD_EXIT2_TT" },
145
  { 28, "PAYLOAD_MONITOR_P_EXIT" },
146
  { 29, "SPAWN_REQUEST" },
147
  { 30, "SPAWN_REQUEST_TT" },
148
  { 31, "SPAWN_REPLY" },
149
  { 32, "SPAWN_REPLY_TT" },
150
  { 33, "ALIAS_SEND" },
151
  { 34, "ALIAS_SEND_TT" },
152
  { 35, "UNLINK_ID" },
153
  { 36, "UNLINK_ID_ACK" },
154
  { DOP_ALTACT_SIG_SEND, "ALTACT_SIG_SEND" },
155
  {  0, NULL }
156
};
157
158
/* Initialize the protocol and registered fields */
159
static int proto_erldp;
160
static int hf_erldp_length_2;
161
static int hf_erldp_length_4;
162
static int hf_etf_version_magic;
163
static int hf_erldp_tag;
164
static int hf_erldp_type;
165
static int hf_erldp_version;
166
static int hf_erldp_flags_v5;
167
static int hf_erldp_flags_v6;
168
static int hf_erldp_flags_published;
169
static int hf_erldp_flags_atom_cache;
170
static int hf_erldp_flags_extended_references;
171
static int hf_erldp_flags_dist_monitor;
172
static int hf_erldp_flags_fun_tags;
173
static int hf_erldp_flags_dist_monitor_name;
174
static int hf_erldp_flags_hidden_atom_cache;
175
static int hf_erldp_flags_new_fun_tags;
176
static int hf_erldp_flags_extended_pids_ports;
177
static int hf_erldp_flags_export_ptr_tag;
178
static int hf_erldp_flags_bit_binaries;
179
static int hf_erldp_flags_new_floats;
180
static int hf_erldp_flags_unicode_io;
181
static int hf_erldp_flags_dist_hdr_atom_cache;
182
static int hf_erldp_flags_small_atom_tags;
183
static int hf_erldp_flags_ets_compressed;
184
static int hf_erldp_flags_utf8_atoms;
185
static int hf_erldp_flags_map_tag;
186
static int hf_erldp_flags_big_creation;
187
static int hf_erldp_flags_send_sender;
188
static int hf_erldp_flags_big_seqtrace_labels;
189
static int hf_erldp_flags_pending_connect;
190
static int hf_erldp_flags_exit_payload;
191
static int hf_erldp_flags_fragments;
192
static int hf_erldp_flags_handshake_23;
193
static int hf_erldp_flags_unlink_id;
194
static int hf_erldp_flags_mandatory_25_digest;
195
static int hf_erldp_flags_reserved;
196
static int hf_erldp_flags_spawn;
197
static int hf_erldp_flags_name_me;
198
static int hf_erldp_flags_v4_nc;
199
static int hf_erldp_flags_alias;
200
static int hf_erldp_flags_local_ext;
201
static int hf_erldp_flags_altact_sig;
202
static int hf_erldp_flags_native_records;
203
static int hf_erldp_flags_spare;
204
static int hf_erldp_flags_high;
205
static int hf_erldp_flags_high_spawn;
206
static int hf_erldp_flags_high_name_me;
207
static int hf_erldp_flags_high_v4_nc;
208
static int hf_erldp_flags_high_alias;
209
static int hf_erldp_flags_high_local_ext;
210
static int hf_erldp_flags_high_altact_sig;
211
static int hf_erldp_flags_high_native_records;
212
static int hf_erldp_flags_high_spare;
213
static int hf_erldp_creation;
214
static int hf_erldp_challenge;
215
static int hf_erldp_digest;
216
static int hf_erldp_nlen;
217
static int hf_erldp_name;
218
static int hf_erldp_status;
219
static int hf_erldp_sequence_id;
220
static int hf_erldp_fragment_id;
221
static int hf_erldp_num_atom_cache_refs;
222
static int hf_erldp_etf_flags;
223
static int hf_erldp_internal_segment_index;
224
static int hf_erldp_atom_length;
225
static int hf_erldp_atom_length2;
226
static int hf_erldp_atom_text;
227
static int hf_erldp_string_ext_len;
228
static int hf_erldp_string_ext;
229
static int hf_erldp_atom_cache_ref;
230
static int hf_erldp_small_int_ext;
231
static int hf_erldp_int_ext;
232
static int hf_erldp_small_big_ext_len;
233
static int hf_erldp_large_big_ext_len;
234
static int hf_erldp_big_ext_int;
235
static int hf_erldp_big_ext_str;
236
static int hf_erldp_big_ext_bytes;
237
static int hf_erldp_float_ext;
238
static int hf_erldp_new_float_ext;
239
static int hf_erldp_port_ext_id;
240
static int hf_erldp_port_ext_v4_id;
241
static int hf_erldp_port_ext_creation;
242
static int hf_erldp_pid_ext_id;
243
static int hf_erldp_pid_ext_serial;
244
static int hf_erldp_pid_ext_creation;
245
static int hf_erldp_list_ext_len;
246
static int hf_erldp_map_ext_len;
247
static int hf_erldp_binary_ext_len;
248
static int hf_erldp_binary_ext_bits;
249
static int hf_erldp_binary_ext;
250
static int hf_erldp_new_ref_ext_len;
251
static int hf_erldp_new_ref_ext_creation;
252
static int hf_erldp_new_ref_ext_id;
253
static int hf_erldp_fun_ext_num_free;
254
static int hf_erldp_new_fun_ext_size;
255
static int hf_erldp_new_fun_ext_arity;
256
static int hf_erldp_new_fun_ext_uniq;
257
static int hf_erldp_new_fun_ext_index;
258
static int hf_erldp_new_fun_ext_num_free;
259
static int hf_erldp_ref_ext_id;
260
static int hf_erldp_local_ext_hash;
261
static int hf_erldp_local_ext_data;
262
static int hf_erldp_undecoded;
263
static int hf_erldp_record_ext_num_fields;
264
static int hf_erldp_record_ext_flags;
265
static int hf_erldp_record_ext_flags_exported;
266
static int hf_erldp_record_ext_flags_reserved;
267
static int hf_erldp_altact_flags;
268
static int hf_erldp_altact_flags_prio;
269
static int hf_erldp_altact_flags_token;
270
static int hf_erldp_altact_flags_alias;
271
static int hf_erldp_altact_flags_name;
272
static int hf_erldp_altact_flags_exit;
273
274
static int hf_etf_tag;
275
static int hf_etf_dist_header_tag;
276
static int hf_etf_dist_header_new_cache;
277
static int hf_etf_dist_header_segment_index;
278
static int hf_etf_dist_header_long_atoms;
279
static int hf_etf_arity4;
280
static int hf_etf_arity;
281
282
static int hf_etf_fragments;
283
static int hf_etf_fragment;
284
static int hf_etf_fragment_overlap;
285
static int hf_etf_fragment_overlap_conflicts;
286
static int hf_etf_fragment_multiple_tails;
287
static int hf_etf_fragment_too_long_fragment;
288
static int hf_etf_fragment_error;
289
static int hf_etf_fragment_count;
290
static int hf_etf_reassembled_in;
291
static int hf_etf_reassembled_length;
292
static int hf_etf_reassembled_data;
293
294
static reassembly_table erldp_reassembly_table;
295
296
/* Initialize the subtree pointers */
297
static int ett_erldp;
298
static int ett_erldp_flags;
299
300
static int ett_etf;
301
static int ett_etf_flags;
302
static int ett_etf_acrs;
303
static int ett_etf_acr;
304
static int ett_etf_tmp;
305
static int ett_etf_altact_flags;
306
static int ett_etf_record_flags;
307
308
static int ett_etf_fragment;
309
static int ett_etf_fragments;
310
311
static expert_field ei_erldp_unknown_tag;
312
313
/* Preferences */
314
static bool erldp_desegment = true;
315
316
/* Dissectors */
317
static dissector_handle_t erldp_handle;
318
319
/* Defragmentation */
320
static const fragment_items etf_frag_items = {
321
    /* Fragment subtrees */
322
    &ett_etf_fragment,
323
    &ett_etf_fragments,
324
    /* Fragment fields */
325
    &hf_etf_fragments,
326
    &hf_etf_fragment,
327
    &hf_etf_fragment_overlap,
328
    &hf_etf_fragment_overlap_conflicts,
329
    &hf_etf_fragment_multiple_tails,
330
    &hf_etf_fragment_too_long_fragment,
331
    &hf_etf_fragment_error,
332
    &hf_etf_fragment_count,
333
    /* Reassembled in field */
334
    &hf_etf_reassembled_in,
335
    /* Reassembled length field */
336
    &hf_etf_reassembled_length,
337
    &hf_etf_reassembled_data,
338
    /* Tag */
339
    "Message fragments"
340
};
341
342
/*--- External Term Format ---*/
343
344
static int dissect_etf_type(const char *label, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
345
static int dissect_etf_type_ret_tree(const char *label, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree **ret_tree);
346
static int dissect_etf_pdu_data(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
347
348
0
static int dissect_etf_dist_header(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree) {
349
0
  uint32_t num, isi;
350
0
  uint8_t flen, flg;
351
0
  int flg_offset, acrs_offset, acr_offset;
352
0
  uint32_t atom_txt_len;
353
0
  bool new_entry, long_atom;
354
0
  proto_item *ti_acrs, *ti_acr, *ti_tmp;
355
0
  proto_tree *flags_tree, *acrs_tree, *acr_tree;
356
0
  const uint8_t *str;
357
358
0
  proto_tree_add_item_ret_uint(tree, hf_erldp_num_atom_cache_refs, tvb, offset, 1, ENC_BIG_ENDIAN, &num);
359
0
  offset++;
360
361
0
  if (num == 0)
362
0
    return offset;
363
364
0
  flg_offset = offset;
365
0
  flen = num / 2 + 1;
366
0
  ti_tmp = proto_tree_add_item(tree, hf_erldp_etf_flags, tvb, offset, flen, ENC_NA );
367
0
  flags_tree = proto_item_add_subtree(ti_tmp, ett_etf_flags);
368
0
  for (unsigned i=0; i<num; i++) {
369
0
    flg = tvb_get_uint8(tvb, offset + i / 2);
370
0
    proto_tree_add_boolean_format_value(flags_tree, hf_etf_dist_header_new_cache, tvb, offset + i / 2, 1,
371
0
                            (flg & (0x08 << 4*(i%2))), "NewCacheEntryFlag[%2d]: %s",
372
0
                            i, (flg & (0x08 << 4*(i%2))) ? "SET" : "---");
373
0
    proto_tree_add_uint_format(flags_tree, hf_etf_dist_header_segment_index, tvb, offset + i / 2, 1,
374
0
                            (flg & (0x07 << 4*(i%2))), "SegmentIndex     [%2d]: %u",
375
0
                            i, (flg & (0x07 << 4*(i%2))));
376
0
  }
377
0
  flg = tvb_get_uint8(tvb, offset + num / 2);
378
0
  proto_tree_add_boolean(flags_tree, hf_etf_dist_header_long_atoms, tvb, offset + num / 2, 1, (flg & (0x01 << 4*(num%2))));
379
0
  long_atom = flg & (0x01 << 4*(num%2));
380
0
  offset += flen;
381
382
0
  acrs_offset = offset;
383
0
  acrs_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_etf_acrs, &ti_acrs, "AtomCacheRefs");
384
0
  for (unsigned i=0; i<num; i++) {
385
0
    flg = tvb_get_uint8(tvb, flg_offset + i / 2);
386
0
    new_entry = flg & (0x08 << 4*(i%2));
387
0
    acr_offset = offset;
388
0
    acr_tree = proto_tree_add_subtree_format(acrs_tree, tvb, offset, 0, ett_etf_acr, &ti_acr, "AtomCacheRef[%2d]:", i);
389
0
    proto_tree_add_item_ret_uint(acr_tree, hf_erldp_internal_segment_index, tvb, offset, 1, ENC_BIG_ENDIAN, &isi);
390
0
    proto_item_append_text(ti_acr, " %3d", isi);
391
0
    offset++;
392
0
    if (!new_entry)
393
0
      continue;
394
0
    if (long_atom) {
395
0
      proto_tree_add_item_ret_uint(acr_tree, hf_erldp_atom_length2, tvb, offset, 2, ENC_BIG_ENDIAN, &atom_txt_len);
396
0
      offset += 2;
397
0
    }
398
0
    else {
399
0
      proto_tree_add_item_ret_uint(acr_tree, hf_erldp_atom_length, tvb, offset, 1, ENC_BIG_ENDIAN, &atom_txt_len);
400
0
      offset++;
401
0
    }
402
0
    proto_tree_add_item_ret_string(acr_tree, hf_erldp_atom_text, tvb, offset, atom_txt_len, ENC_NA|ENC_ASCII, pinfo->pool, &str);
403
0
    proto_item_append_text(ti_acr, " - '%s'", str);
404
0
    offset += atom_txt_len;
405
0
    proto_item_set_len(ti_acr, offset - acr_offset);
406
0
  }
407
0
  proto_item_set_len(ti_acrs, offset - acrs_offset);
408
409
0
  return offset;
410
0
}
411
412
// NOLINTNEXTLINE(misc-no-recursion)
413
0
static int dissect_etf_tuple_content(bool large, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree, const char **value_str _U_) {
414
0
  uint32_t arity, i;
415
416
0
  if (large) {
417
0
    proto_tree_add_item_ret_uint(tree, hf_etf_arity4, tvb, offset, 4, ENC_BIG_ENDIAN, &arity);
418
0
    offset += 4;
419
0
  } else {
420
0
    proto_tree_add_item_ret_uint(tree, hf_etf_arity, tvb, offset, 1, ENC_BIG_ENDIAN, &arity);
421
0
    offset++;
422
0
  }
423
0
  for (i=0; i<arity; i++) {
424
0
    offset = dissect_etf_type(NULL, pinfo, tvb, offset, tree);
425
0
  }
426
427
0
  return offset;
428
0
}
429
430
0
static int dissect_etf_big_ext(tvbuff_t *tvb, packet_info *pinfo, int offset, uint32_t len, proto_tree *tree, const char **value_str) {
431
0
      uint8_t sign;
432
0
      int32_t i;
433
434
0
      sign = tvb_get_uint8(tvb, offset);
435
0
      offset += 1;
436
437
0
      if (len <= 8) {
438
0
        uint64_t big_val = 0;
439
440
0
        switch (len) {
441
0
        case 1: big_val = tvb_get_uint8(tvb, offset); break;
442
0
        case 2: big_val = tvb_get_letohs(tvb, offset); break;
443
0
        case 3: big_val = tvb_get_letoh24(tvb, offset); break;
444
0
        case 4: big_val = tvb_get_letohl(tvb, offset); break;
445
0
        case 5: big_val = tvb_get_letoh40(tvb, offset); break;
446
0
        case 6: big_val = tvb_get_letoh48(tvb, offset); break;
447
0
        case 7: big_val = tvb_get_letoh56(tvb, offset); break;
448
0
        case 8: big_val = tvb_get_letoh64(tvb, offset); break;
449
0
        }
450
0
        proto_tree_add_uint64_format_value(tree, hf_erldp_big_ext_int, tvb, offset, len,
451
0
                                           big_val, "%s%" PRIu64, sign ? "-"  : "", big_val);
452
0
        if (value_str)
453
0
          *value_str = wmem_strdup_printf(pinfo->pool, "%s%" PRIu64,
454
0
                                          sign ? "-"  : "", big_val);
455
0
      } else if (len < 64) {
456
0
        wmem_strbuf_t *strbuf = wmem_strbuf_new_sized(pinfo->pool, len*1+3+1);
457
458
0
        wmem_strbuf_append(strbuf, "0x");
459
0
        for (i = len - 1; i >= 0; i--) {
460
0
          wmem_strbuf_append_printf(strbuf, "%02x", tvb_get_uint8(tvb, offset + i));
461
0
        }
462
0
        char *buf = wmem_strbuf_finalize(strbuf);
463
464
0
        proto_tree_add_string_format_value(tree, hf_erldp_big_ext_str, tvb, offset, len, buf, "%s", buf);
465
466
0
        if (value_str)
467
0
          *value_str = buf;
468
0
      } else {
469
        /* len is from the packet: do not let a huge value wrap offset */
470
0
        tvb_ensure_bytes_exist64(tvb, offset, len);
471
0
        proto_tree_add_item(tree, hf_erldp_big_ext_bytes, tvb, offset, len, ENC_NA);
472
0
      }
473
474
0
      return offset + len;
475
0
}
476
477
// NOLINTNEXTLINE(misc-no-recursion)
478
0
static int dissect_etf_type_content(uint8_t tag, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree, const char **value_str) {
479
0
  int32_t int_val;
480
0
  uint32_t len, i, uint_val;
481
0
  uint32_t id;
482
0
  const uint8_t *str_val;
483
484
0
  static int * const record_flags[] = {
485
0
    &hf_erldp_record_ext_flags_reserved,
486
0
    &hf_erldp_record_ext_flags_exported,
487
0
    NULL
488
0
  };
489
490
0
  increment_dissection_depth(pinfo);
491
492
0
  switch (tag) {
493
0
    case ATOM_CACHE_REF:
494
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_atom_cache_ref, tvb, offset, 1, ENC_BIG_ENDIAN, &uint_val);
495
0
      offset += 1;
496
0
      if (value_str)
497
0
        *value_str = wmem_strdup_printf(pinfo->pool, "%d", uint_val);
498
0
      break;
499
500
0
    case SMALL_INTEGER_EXT:
501
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_small_int_ext, tvb, offset, 1, ENC_BIG_ENDIAN, &uint_val);
502
0
      offset += 1;
503
0
      if (value_str)
504
0
        *value_str = wmem_strdup_printf(pinfo->pool, "%u", uint_val);
505
0
      break;
506
507
0
    case INTEGER_EXT:
508
0
      proto_tree_add_item_ret_int(tree, hf_erldp_int_ext, tvb, offset, 4, ENC_BIG_ENDIAN, &int_val);
509
0
      offset += 4;
510
0
      if (value_str)
511
0
        *value_str = wmem_strdup_printf(pinfo->pool, "%d", int_val);
512
0
      break;
513
514
0
    case SMALL_BIG_EXT: {
515
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_small_big_ext_len, tvb, offset, 1, ENC_BIG_ENDIAN, &len);
516
0
      offset += 1;
517
518
0
      offset = dissect_etf_big_ext(tvb, pinfo, offset, len, tree, value_str);
519
0
      break;
520
0
    }
521
522
0
    case LARGE_BIG_EXT: {
523
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_large_big_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
524
0
      offset += 4;
525
526
0
      offset = dissect_etf_big_ext(tvb, pinfo, offset, len, tree, value_str);
527
0
      break;
528
0
    }
529
530
0
    case FLOAT_EXT:
531
0
      proto_tree_add_item_ret_string(tree, hf_erldp_float_ext, tvb, offset, 31, ENC_NA|ENC_UTF_8, pinfo->pool, &str_val);
532
0
      offset += 31;
533
0
      if (value_str)
534
0
        *value_str = (const char *)str_val;
535
0
      break;
536
537
0
    case NEW_FLOAT_EXT:
538
0
      proto_tree_add_item(tree, hf_erldp_new_float_ext, tvb, offset, 8, ENC_BIG_ENDIAN);
539
0
      if (value_str) {
540
0
        double   new_float_val = tvb_get_ntohieee_double(tvb, offset);
541
0
        *value_str = wmem_strdup_printf(pinfo->pool, "%f", new_float_val);
542
0
      }
543
0
      offset += 8;
544
0
      break;
545
546
0
    case ATOM_UTF8_EXT:
547
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_atom_length2, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
548
0
      offset += 2;
549
0
      proto_tree_add_item_ret_string(tree, hf_erldp_atom_text, tvb, offset, len, ENC_NA|ENC_UTF_8, pinfo->pool, &str_val);
550
0
      offset += len;
551
0
      if (value_str)
552
0
        *value_str = (const char *)str_val;
553
0
      break;
554
555
0
    case ATOM_EXT:
556
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_atom_length2, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
557
0
      offset += 2;
558
0
      proto_tree_add_item_ret_string(tree, hf_erldp_atom_text, tvb, offset, len, ENC_NA|ENC_ISO_8859_1, pinfo->pool, &str_val);
559
0
      offset += len;
560
0
      if (value_str)
561
0
        *value_str = (const char *)str_val;
562
0
      break;
563
564
0
    case SMALL_ATOM_EXT:
565
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_atom_length, tvb, offset, 1, ENC_BIG_ENDIAN, &len);
566
0
      offset++;
567
0
      proto_tree_add_item_ret_string(tree, hf_erldp_atom_text, tvb, offset, len, ENC_NA|ENC_ISO_8859_1, pinfo->pool, &str_val);
568
0
      offset += len;
569
0
      if (value_str)
570
0
        *value_str = (const char *)str_val;
571
0
      break;
572
573
0
    case SMALL_ATOM_UTF8_EXT:
574
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_atom_length, tvb, offset, 1, ENC_BIG_ENDIAN, &len);
575
0
      offset++;
576
0
      proto_tree_add_item_ret_string(tree, hf_erldp_atom_text, tvb, offset, len, ENC_NA|ENC_UTF_8, pinfo->pool, &str_val);
577
0
      offset += len;
578
0
      if (value_str)
579
0
        *value_str = (const char *)str_val;
580
0
      break;
581
582
0
    case STRING_EXT:
583
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_string_ext_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
584
0
      offset += 2;
585
0
      proto_tree_add_item_ret_string(tree, hf_erldp_string_ext, tvb, offset, len, ENC_NA|ENC_UTF_8, pinfo->pool, &str_val);
586
0
      offset += len;
587
0
      if (value_str)
588
0
        *value_str = (const char *)str_val;
589
0
      break;
590
591
0
    case PORT_EXT:
592
0
      offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
593
0
      proto_tree_add_item(tree, hf_erldp_port_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
594
0
      offset += 4;
595
0
      proto_tree_add_item(tree, hf_erldp_port_ext_creation, tvb, offset, 1, ENC_BIG_ENDIAN);
596
0
      offset++;
597
0
      break;
598
599
0
    case NEW_PORT_EXT:
600
0
      offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
601
0
      proto_tree_add_item(tree, hf_erldp_port_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
602
0
      offset += 4;
603
0
      proto_tree_add_item(tree, hf_erldp_port_ext_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
604
0
      offset += 4;
605
0
      break;
606
607
0
    case V4_PORT_EXT:
608
0
      offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
609
0
      proto_tree_add_item(tree, hf_erldp_port_ext_v4_id, tvb, offset, 8, ENC_BIG_ENDIAN);
610
0
      offset += 8;
611
0
      proto_tree_add_item(tree, hf_erldp_port_ext_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
612
0
      offset += 4;
613
0
      break;
614
615
0
    case PID_EXT:
616
0
      offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
617
0
      proto_tree_add_item(tree, hf_erldp_pid_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
618
0
      offset += 4;
619
0
      proto_tree_add_item(tree, hf_erldp_pid_ext_serial, tvb, offset, 4, ENC_BIG_ENDIAN);
620
0
      offset += 4;
621
0
      proto_tree_add_item(tree, hf_erldp_pid_ext_creation, tvb, offset, 1, ENC_BIG_ENDIAN);
622
0
      offset++;
623
0
      break;
624
625
0
    case NEW_PID_EXT:
626
0
      offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
627
0
      proto_tree_add_item(tree, hf_erldp_pid_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
628
0
      offset += 4;
629
0
      proto_tree_add_item(tree, hf_erldp_pid_ext_serial, tvb, offset, 4, ENC_BIG_ENDIAN);
630
0
      offset += 4;
631
0
      proto_tree_add_item(tree, hf_erldp_pid_ext_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
632
0
      offset += 4;
633
0
      break;
634
635
0
    case SMALL_TUPLE_EXT:
636
0
      offset = dissect_etf_tuple_content(false, pinfo, tvb, offset, tree, value_str);
637
0
      break;
638
639
0
    case LARGE_TUPLE_EXT:
640
0
      offset = dissect_etf_tuple_content(true, pinfo, tvb, offset, tree, value_str);
641
0
      break;
642
643
0
    case NIL_EXT:
644
0
      break;
645
646
0
    case LIST_EXT:
647
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_list_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
648
0
      offset += 4;
649
0
      for (i=0; i<len; i++) {
650
0
        offset = dissect_etf_type(NULL, pinfo, tvb, offset, tree);
651
0
      }
652
0
      offset = dissect_etf_type("Tail", pinfo, tvb, offset, tree);
653
0
      break;
654
655
0
    case MAP_EXT:
656
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_map_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
657
0
      offset += 4;
658
0
      for (i=0; i<len; i++) {
659
        // key
660
0
        offset = dissect_etf_type(NULL, pinfo, tvb, offset, tree);
661
        // value
662
0
        offset = dissect_etf_type(NULL, pinfo, tvb, offset, tree);
663
0
      }
664
0
      break;
665
666
0
    case BINARY_EXT:
667
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_binary_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
668
0
      offset += 4;
669
0
      tvb_ensure_bytes_exist64(tvb, offset, len);
670
0
      proto_tree_add_item(tree, hf_erldp_binary_ext, tvb, offset, len, ENC_NA);
671
0
      offset += len;
672
0
      break;
673
674
0
    case BIT_BINARY_EXT:
675
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_binary_ext_len, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
676
0
      offset += 4;
677
0
      proto_tree_add_item(tree, hf_erldp_binary_ext_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
678
0
      offset++;
679
0
      tvb_ensure_bytes_exist64(tvb, offset, len);
680
0
      proto_tree_add_item(tree, hf_erldp_binary_ext, tvb, offset, len, ENC_NA);
681
0
      offset += len;
682
0
      break;
683
684
0
    case REFERENCE_EXT:
685
0
      offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
686
0
      proto_tree_add_item(tree, hf_erldp_ref_ext_id, tvb, offset, 4, ENC_BIG_ENDIAN);
687
0
      offset += 4;
688
0
      proto_tree_add_item(tree, hf_erldp_new_ref_ext_creation, tvb, offset, 1, ENC_BIG_ENDIAN);
689
0
      offset++;
690
0
      break;
691
692
0
    case NEW_REFERENCE_EXT:
693
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_new_ref_ext_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
694
0
      offset += 2;
695
0
      offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
696
0
      proto_tree_add_item(tree, hf_erldp_new_ref_ext_creation, tvb, offset, 1, ENC_BIG_ENDIAN);
697
0
      offset++;
698
0
      for (i=0; i<len; i++) {
699
0
        id = tvb_get_ntohl(tvb, offset);
700
0
        proto_tree_add_uint_format(tree, hf_erldp_new_ref_ext_id, tvb, offset, 4,
701
0
                            id, "ID[%d]: 0x%08X", i, id);
702
0
        offset += 4;
703
0
      }
704
0
      break;
705
706
0
    case NEWER_REFERENCE_EXT:
707
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_new_ref_ext_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
708
0
      offset += 2;
709
0
      offset = dissect_etf_type("Node", pinfo, tvb, offset, tree);
710
0
      proto_tree_add_item(tree, hf_erldp_new_ref_ext_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
711
0
      offset += 4;
712
0
      for (i=0; i<len; i++) {
713
0
        id = tvb_get_ntohl(tvb, offset);
714
0
        proto_tree_add_uint_format(tree, hf_erldp_new_ref_ext_id, tvb, offset, 4,
715
0
                            id, "ID[%d]: 0x%08X", i, id);
716
0
        offset += 4;
717
0
      }
718
0
      break;
719
720
0
    case FUN_EXT:
721
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_fun_ext_num_free, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
722
0
      offset += 4;
723
0
      offset = dissect_etf_type("Pid", pinfo, tvb, offset, tree);
724
0
      offset = dissect_etf_type("Module", pinfo, tvb, offset, tree);
725
0
      offset = dissect_etf_type("Index", pinfo, tvb, offset, tree);
726
0
      offset = dissect_etf_type("Unique", pinfo, tvb, offset, tree);
727
728
0
      for (i = 0; i < len; i++) {
729
0
          char buf[ITEM_LABEL_LENGTH];
730
0
          snprintf(buf, sizeof(buf), "Free Var[%u]", i + 1);
731
0
          offset = dissect_etf_type(buf, pinfo, tvb, offset, tree);
732
0
      }
733
0
      break;
734
735
0
    case NEW_FUN_EXT:
736
0
      proto_tree_add_item(tree, hf_erldp_new_fun_ext_size, tvb, offset, 4, ENC_BIG_ENDIAN);
737
0
      offset += 4;
738
0
      proto_tree_add_item(tree, hf_erldp_new_fun_ext_arity, tvb, offset, 1, ENC_BIG_ENDIAN);
739
0
      offset += 1;
740
0
      proto_tree_add_item(tree, hf_erldp_new_fun_ext_uniq, tvb, offset, 16, ENC_NA);
741
0
      offset += 16;
742
0
      proto_tree_add_item(tree, hf_erldp_new_fun_ext_index, tvb, offset, 4, ENC_BIG_ENDIAN);
743
0
      offset += 4;
744
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_new_fun_ext_num_free, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
745
0
      offset += 4;
746
0
      offset = dissect_etf_type("Module", pinfo, tvb, offset, tree);
747
0
      offset = dissect_etf_type("OldIndex", pinfo, tvb, offset, tree);
748
0
      offset = dissect_etf_type("OldUnique", pinfo, tvb, offset, tree);
749
0
      offset = dissect_etf_type("Pid", pinfo, tvb, offset, tree);
750
751
0
      for (i = 0; i < len; i++) {
752
0
          char buf[ITEM_LABEL_LENGTH];
753
0
          snprintf(buf, sizeof(buf), "Free Var[%u]", i + 1);
754
0
          offset = dissect_etf_type(buf, pinfo, tvb, offset, tree);
755
0
      }
756
0
      break;
757
758
0
    case EXPORT_EXT:
759
0
      offset = dissect_etf_type("Module", pinfo, tvb, offset, tree);
760
0
      offset = dissect_etf_type("Function", pinfo, tvb, offset, tree);
761
0
      offset = dissect_etf_type("Arity", pinfo, tvb, offset, tree);
762
0
      break;
763
764
0
    case RECORD_EXT:
765
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_record_ext_num_fields, tvb, offset, 4, ENC_BIG_ENDIAN, &len);
766
0
      offset += 4;
767
0
      proto_tree_add_bitmask(tree, tvb, offset, hf_erldp_record_ext_flags,
768
0
                             ett_etf_record_flags, record_flags, ENC_NA);
769
0
      offset += 1;
770
0
      offset = dissect_etf_type("Module", pinfo, tvb, offset, tree);
771
0
      offset = dissect_etf_type("Name", pinfo, tvb, offset, tree);
772
773
0
      for (i = 0; i < len; i++) {
774
0
          char buf[ITEM_LABEL_LENGTH];
775
0
          snprintf(buf, sizeof(buf), "Field Name[%u]", i + 1);
776
0
          offset = dissect_etf_type(buf, pinfo, tvb, offset, tree);
777
0
      }
778
0
      for (i = 0; i < len; i++) {
779
0
          char buf[ITEM_LABEL_LENGTH];
780
0
          snprintf(buf, sizeof(buf), "Value[%u]", i + 1);
781
0
          offset = dissect_etf_type(buf, pinfo, tvb, offset, tree);
782
0
      }
783
0
      break;
784
785
0
    case LOCAL_EXT:
786
      /* A hash, then an encoding known only to the node that made it */
787
0
      proto_tree_add_item(tree, hf_erldp_local_ext_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
788
0
      offset += 4;
789
0
      len = tvb_reported_length_remaining(tvb, offset);
790
0
      if (len > 0)
791
0
        proto_tree_add_item(tree, hf_erldp_local_ext_data, tvb, offset, len, ENC_NA);
792
0
      offset += len;
793
0
      break;
794
795
0
    default:
796
      /* Its length is unknown, so nothing after it can be decoded */
797
0
      proto_tree_add_expert(tree, pinfo, &ei_erldp_unknown_tag, tvb, offset - 1, 1);
798
0
      len = tvb_reported_length_remaining(tvb, offset);
799
0
      if (len > 0)
800
0
        proto_tree_add_item(tree, hf_erldp_undecoded, tvb, offset, len, ENC_NA);
801
0
      offset += len;
802
0
      break;
803
0
  }
804
805
0
  decrement_dissection_depth(pinfo);
806
807
0
  return offset;
808
0
}
809
810
0
static int dissect_etf_pdu_data(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree) {
811
0
  uint8_t ctl_op = 0;
812
0
  int ctl_offset = offset;
813
0
  proto_tree *ctl_tree = NULL;
814
815
0
  static int * const altact_flags[] = {
816
0
    &hf_erldp_altact_flags_prio,
817
0
    &hf_erldp_altact_flags_token,
818
0
    &hf_erldp_altact_flags_alias,
819
0
    &hf_erldp_altact_flags_name,
820
0
    &hf_erldp_altact_flags_exit,
821
0
    NULL
822
0
  };
823
824
0
  if ((tvb_get_uint8(tvb, offset) == SMALL_TUPLE_EXT) && (tvb_get_uint8(tvb, offset + 2) == SMALL_INTEGER_EXT)) {
825
0
    ctl_op = tvb_get_uint8(tvb, offset + 3);
826
0
    col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, ctl_op, VALS(erldp_ctlmsg_vals), "unknown ControlMessage operation (%d)"));
827
0
  }
828
0
  offset = dissect_etf_type_ret_tree("ControlMessage", pinfo, tvb, offset, tree, &ctl_tree);
829
830
  /* {37, Flags, SenderPid, To} or {37, Flags, SenderPid, To, Token} */
831
0
  if ((ctl_op == DOP_ALTACT_SIG_SEND) && (tvb_get_uint8(tvb, ctl_offset + 1) >= 4) &&
832
0
      (tvb_get_uint8(tvb, ctl_offset + 4) == SMALL_INTEGER_EXT)) {
833
0
    proto_tree_add_bitmask(ctl_tree, tvb, ctl_offset + 5, hf_erldp_altact_flags,
834
0
                           ett_etf_altact_flags, altact_flags, ENC_NA);
835
0
  }
836
0
  if (tvb_reported_length_remaining(tvb, offset) > 0)
837
0
    offset = dissect_etf_type("Message", pinfo, tvb, offset, tree);
838
839
0
  return offset;
840
0
}
841
842
0
static int dissect_etf_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const char *label) {
843
0
  int offset = 0;
844
0
  uint8_t mag;
845
0
  uint32_t tag;
846
0
  proto_item *ti;
847
0
  proto_tree *etf_tree;
848
849
0
  mag = tvb_get_uint8(tvb, offset);
850
0
  if (mag != VERSION_MAGIC) {
851
0
    return 0;
852
0
  }
853
854
0
  etf_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_etf, &ti, (label) ? label : "External Term Format");
855
856
0
  proto_tree_add_item(etf_tree, hf_etf_version_magic, tvb, offset, 1, ENC_BIG_ENDIAN);
857
0
  offset++;
858
859
0
  proto_tree_add_item_ret_uint(etf_tree, hf_etf_dist_header_tag, tvb, offset, 1, ENC_BIG_ENDIAN, &tag);
860
0
  offset++;
861
862
0
  if (!label)
863
0
    proto_item_set_text(ti, "%s", val_to_str(pinfo->pool, tag, VALS(etf_header_tag_vals), "unknown tag (%d)"));
864
865
0
  switch (tag) {
866
0
    case DIST_HEADER:
867
0
      offset = dissect_etf_dist_header(pinfo, tvb, offset, etf_tree);
868
0
      proto_item_set_len(ti, offset);
869
870
0
      dissect_etf_pdu_data(pinfo, tvb, offset, tree);
871
0
      break;
872
873
0
    case DIST_FRAG_HEADER:
874
0
    case DIST_FRAG_CONT:
875
0
    {
876
0
      uint64_t sequence_id, fragment_id;
877
0
      bool save_fragmented;
878
0
      fragment_head *frag_msg = NULL;
879
0
      tvbuff_t *next_tvb = NULL;
880
0
      int len_rem;
881
882
0
      proto_tree_add_item_ret_uint64(etf_tree, hf_erldp_sequence_id, tvb, offset, 8, ENC_BIG_ENDIAN, &sequence_id);
883
0
      offset += 8;
884
885
0
      proto_tree_add_item_ret_uint64(etf_tree, hf_erldp_fragment_id, tvb, offset, 8, ENC_BIG_ENDIAN, &fragment_id);
886
0
      offset += 8;
887
888
0
      save_fragmented = pinfo->fragmented;
889
890
0
      len_rem = tvb_reported_length_remaining(tvb, offset);
891
0
      if (len_rem <= 0)
892
0
        return offset;
893
894
0
      pinfo->fragmented = true;
895
896
0
      frag_msg = fragment_add_seq_next(&erldp_reassembly_table,
897
0
                                       tvb, offset, pinfo, (uint32_t)sequence_id, NULL,
898
0
                                       len_rem, fragment_id != 1);
899
900
0
      next_tvb = process_reassembled_data(tvb, offset, pinfo,
901
0
                                          "Reassembled ErlDP", frag_msg,
902
0
                                          &etf_frag_items, NULL, tree);
903
904
0
      if (next_tvb == NULL)
905
0
      { /* make a new subset */
906
0
        next_tvb = tvb_new_subset_remaining(tvb, offset);
907
0
        call_data_dissector(next_tvb, pinfo, tree);
908
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " (Fragment ID: %" PRIu64 ")", fragment_id);
909
0
      }
910
0
      else
911
0
      {
912
0
        offset = dissect_etf_dist_header(pinfo, next_tvb, 0, etf_tree);
913
0
        proto_item_set_len(ti, offset);
914
915
0
        dissect_etf_pdu_data(pinfo, next_tvb, offset, tree);
916
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " (Reassembled, Fragment ID: %" PRIu64 ")", fragment_id);
917
0
      }
918
919
0
      pinfo->fragmented = save_fragmented;
920
0
      offset = tvb_reported_length_remaining(tvb, offset);
921
0
      break;
922
0
    }
923
0
  }
924
925
0
  return offset;
926
0
}
927
928
0
static int dissect_etf_versioned_type(const char *label, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree) {
929
0
  if (tvb_get_uint8(tvb, offset) != VERSION_MAGIC) {
930
0
    proto_tree_add_item(tree, hf_erldp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
931
0
    col_set_str(pinfo->cinfo, COL_INFO, "unknown header format");
932
0
    return offset + 1;
933
0
  }
934
0
  offset += 1;
935
936
0
  return dissect_etf_type(label, pinfo, tvb, offset, tree);
937
0
}
938
939
// NOLINTNEXTLINE(misc-no-recursion)
940
0
static int dissect_etf_type(const char *label, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree) {
941
0
  return dissect_etf_type_ret_tree(label, pinfo, tvb, offset, tree, NULL);
942
0
}
943
944
// NOLINTNEXTLINE(misc-no-recursion)
945
0
static int dissect_etf_type_ret_tree(const char *label, packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree **ret_tree) {
946
0
  int begin = offset;
947
0
  uint32_t tag;
948
0
  proto_item *ti;
949
0
  proto_tree *etf_tree;
950
0
  const char *value_str = NULL;
951
952
0
  etf_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_etf, &ti, (label) ? label : "External Term Format");
953
954
0
  proto_tree_add_item_ret_uint(etf_tree, hf_etf_tag, tvb, offset, 1, ENC_BIG_ENDIAN, &tag);
955
0
  offset++;
956
957
0
  if (!label)
958
0
    proto_item_set_text(ti, "%s", val_to_str(pinfo->pool, tag, VALS(etf_tag_vals), "unknown tag (%d)"));
959
960
0
  offset = dissect_etf_type_content(tag, pinfo, tvb, offset, etf_tree, &value_str);
961
0
  if (value_str)
962
0
    proto_item_append_text(ti, ": %s", value_str);
963
964
0
  proto_item_set_len(ti, offset - begin);
965
966
0
  if (ret_tree)
967
0
    *ret_tree = etf_tree;
968
969
0
  return offset;
970
0
}
971
972
0
static bool is_handshake(tvbuff_t *tvb, int offset) {
973
0
  uint32_t len = tvb_get_ntohs(tvb, offset);
974
0
  uint8_t tag = tvb_get_uint8(tvb, offset + 2);
975
0
  return ((len > 0) && (tag != 0) && strchr("nNcras", tag) && (len == (uint32_t)tvb_captured_length_remaining(tvb, offset + 2)));
976
0
}
977
978
/*--- dissect_erldp_handshake -------------------------------------------------*/
979
0
static void dissect_erldp_handshake(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
980
0
  int offset = 0;
981
0
  uint32_t tag;
982
0
  bool is_challenge = false;
983
0
  uint32_t str_len;
984
0
  const uint8_t *str;
985
986
  /* The flags above bit 31, as the complement message carries them */
987
0
  static int * const erldp_flags_high_flags[] = {
988
0
    &hf_erldp_flags_high_spare,
989
0
    &hf_erldp_flags_high_native_records,
990
0
    &hf_erldp_flags_high_altact_sig,
991
0
    &hf_erldp_flags_high_local_ext,
992
0
    &hf_erldp_flags_high_alias,
993
0
    &hf_erldp_flags_high_v4_nc,
994
0
    &hf_erldp_flags_high_name_me,
995
0
    &hf_erldp_flags_high_spawn,
996
0
    NULL
997
0
  };
998
999
0
  static int * const erldp_flags_flags[] = {
1000
0
    &hf_erldp_flags_spare,
1001
0
    &hf_erldp_flags_native_records,
1002
0
    &hf_erldp_flags_altact_sig,
1003
0
    &hf_erldp_flags_local_ext,
1004
0
    &hf_erldp_flags_alias,
1005
0
    &hf_erldp_flags_v4_nc,
1006
0
    &hf_erldp_flags_name_me,
1007
0
    &hf_erldp_flags_spawn,
1008
0
    &hf_erldp_flags_reserved,
1009
0
    &hf_erldp_flags_mandatory_25_digest,
1010
0
    &hf_erldp_flags_unlink_id,
1011
0
    &hf_erldp_flags_handshake_23,
1012
0
    &hf_erldp_flags_fragments,
1013
0
    &hf_erldp_flags_exit_payload,
1014
0
    &hf_erldp_flags_pending_connect,
1015
0
    &hf_erldp_flags_big_seqtrace_labels,
1016
0
    &hf_erldp_flags_send_sender,
1017
0
    &hf_erldp_flags_big_creation,
1018
0
    &hf_erldp_flags_map_tag,
1019
0
    &hf_erldp_flags_utf8_atoms,
1020
0
    &hf_erldp_flags_ets_compressed,
1021
0
    &hf_erldp_flags_small_atom_tags,
1022
0
    &hf_erldp_flags_dist_hdr_atom_cache,
1023
0
    &hf_erldp_flags_unicode_io,
1024
0
    &hf_erldp_flags_new_floats,
1025
0
    &hf_erldp_flags_bit_binaries,
1026
0
    &hf_erldp_flags_export_ptr_tag,
1027
0
    &hf_erldp_flags_extended_pids_ports,
1028
0
    &hf_erldp_flags_new_fun_tags,
1029
0
    &hf_erldp_flags_hidden_atom_cache,
1030
0
    &hf_erldp_flags_dist_monitor_name,
1031
0
    &hf_erldp_flags_fun_tags,
1032
0
    &hf_erldp_flags_dist_monitor,
1033
0
    &hf_erldp_flags_extended_references,
1034
0
    &hf_erldp_flags_atom_cache,
1035
0
    &hf_erldp_flags_published,
1036
0
    NULL
1037
0
  };
1038
1039
0
  proto_tree_add_item(tree, hf_erldp_length_2, tvb, offset, 2, ENC_BIG_ENDIAN);
1040
0
  offset += 2;
1041
0
  proto_tree_add_item_ret_uint(tree, hf_erldp_tag, tvb, offset, 1, ENC_ASCII, &tag);
1042
0
  offset++;
1043
1044
0
  switch (tag) {
1045
0
    case 'n' :
1046
0
      proto_tree_add_item(tree, hf_erldp_version, tvb, offset, 2, ENC_BIG_ENDIAN);
1047
0
      offset += 2;
1048
1049
0
      proto_tree_add_bitmask(tree, tvb, offset, hf_erldp_flags_v5,
1050
0
         ett_erldp_flags, erldp_flags_flags, ENC_BIG_ENDIAN);
1051
0
      offset += 4;
1052
0
      if (tvb_bytes_exist(tvb, offset, 4)) {
1053
0
        if (!tvb_ascii_isprint(tvb, offset, 4)) {
1054
0
          is_challenge = true;
1055
0
        }
1056
0
      }
1057
0
      if (is_challenge) {
1058
0
        proto_tree_add_item(tree, hf_erldp_challenge, tvb, offset, 4, ENC_BIG_ENDIAN);
1059
0
        offset += 4;
1060
0
      }
1061
0
      str_len = tvb_captured_length_remaining(tvb, offset);
1062
0
      proto_tree_add_item_ret_string(tree, hf_erldp_name, tvb, offset, str_len, ENC_ASCII|ENC_NA, pinfo->pool, &str);
1063
0
      col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", (is_challenge) ? "SEND_CHALLENGE" : "SEND_NAME", str);
1064
0
      break;
1065
1066
0
    case 'N':
1067
0
      proto_tree_add_bitmask(tree, tvb, offset, hf_erldp_flags_v6,
1068
0
         ett_erldp_flags, erldp_flags_flags, ENC_BIG_ENDIAN);
1069
0
      offset += 8;
1070
0
      if (tvb_bytes_exist(tvb, offset + 6, 4)) {
1071
0
        if (!tvb_ascii_isprint(tvb, offset + 6, 4)) {
1072
0
          is_challenge = true;
1073
0
        }
1074
0
      }
1075
0
      if (is_challenge) {
1076
0
        proto_tree_add_item(tree, hf_erldp_challenge, tvb, offset, 4, ENC_BIG_ENDIAN);
1077
0
        offset += 4;
1078
0
      }
1079
0
      proto_tree_add_item(tree, hf_erldp_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
1080
0
      offset += 4;
1081
0
      proto_tree_add_item_ret_uint(tree, hf_erldp_nlen, tvb, offset, 2, ENC_BIG_ENDIAN, &str_len);
1082
0
      offset += 2;
1083
0
      proto_tree_add_item_ret_string(tree, hf_erldp_name, tvb, offset, str_len, ENC_ASCII|ENC_NA, pinfo->pool, &str);
1084
0
      col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", (is_challenge) ? "SEND_CHALLENGE" : "SEND_NAME", str);
1085
0
      break;
1086
1087
0
    case 'c' :
1088
0
      proto_tree_add_bitmask(tree, tvb, offset, hf_erldp_flags_high,
1089
0
         ett_erldp_flags, erldp_flags_high_flags, ENC_BIG_ENDIAN);
1090
0
      offset += 4;
1091
0
      proto_tree_add_item(tree, hf_erldp_creation, tvb, offset, 4, ENC_BIG_ENDIAN);
1092
      /*offset += 4;*/
1093
0
      col_set_str(pinfo->cinfo, COL_INFO, "SEND_COMPLEMENT");
1094
0
      break;
1095
1096
0
    case 'r' :
1097
0
      proto_tree_add_item(tree, hf_erldp_challenge, tvb, offset, 4, ENC_BIG_ENDIAN);
1098
0
      offset += 4;
1099
0
      proto_tree_add_item(tree, hf_erldp_digest, tvb, offset, 16, ENC_NA);
1100
      /*offset += 16;*/
1101
0
      col_set_str(pinfo->cinfo, COL_INFO, "SEND_CHALLENGE_REPLY");
1102
0
      break;
1103
1104
0
    case 'a' :
1105
0
      proto_tree_add_item(tree, hf_erldp_digest, tvb, offset, 16, ENC_NA);
1106
      /*offset += 16;*/
1107
0
      col_set_str(pinfo->cinfo, COL_INFO, "SEND_CHALLENGE_ACK");
1108
0
      break;
1109
1110
0
    case 's' :
1111
0
      str_len = tvb_captured_length_remaining(tvb, offset);
1112
0
      proto_tree_add_item_ret_string(tree, hf_erldp_status, tvb, offset, str_len, ENC_ASCII|ENC_NA, pinfo->pool, &str);
1113
0
      col_add_fstr(pinfo->cinfo, COL_INFO, "SEND_STATUS %s", str);
1114
0
      break;
1115
0
  }
1116
0
}
1117
1118
/*--- dissect_erldp_pdu -------------------------------------------------*/
1119
0
static int dissect_erldp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
1120
0
  int offset;
1121
0
  uint32_t msg_len;
1122
0
  uint8_t type;
1123
0
  proto_tree *erldp_tree;
1124
0
  proto_item *ti;
1125
0
  tvbuff_t *next_tvb = NULL;
1126
1127
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "ErlDP");
1128
1129
0
  ti = proto_tree_add_item(tree, proto_erldp, tvb, 0, -1, ENC_NA);
1130
0
  erldp_tree = proto_item_add_subtree(ti, ett_erldp);
1131
1132
0
  if (is_handshake(tvb, 0)) {
1133
0
    dissect_erldp_handshake(tvb, pinfo, erldp_tree);
1134
0
    return tvb_captured_length(tvb);
1135
0
  }
1136
1137
0
  offset = 0;
1138
1139
0
  proto_tree_add_item_ret_uint(erldp_tree, hf_erldp_length_4, tvb, offset, 4, ENC_BIG_ENDIAN, &msg_len);
1140
0
  offset += 4;
1141
1142
0
  if (msg_len == 0) {
1143
0
    col_set_str(pinfo->cinfo, COL_INFO, "KEEP_ALIVE");
1144
0
    return offset;
1145
0
  }
1146
1147
0
  type = tvb_get_uint8(tvb, offset);
1148
0
  switch (type) {
1149
0
    case ERL_PASS_THROUGH:
1150
0
      proto_tree_add_item(erldp_tree, hf_erldp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1151
0
      offset += 1;
1152
1153
0
      offset = dissect_etf_versioned_type("ControlMessage", pinfo, tvb, offset, erldp_tree);
1154
0
      if (tvb_reported_length_remaining(tvb, offset) > 0) {
1155
0
        dissect_etf_versioned_type("Message", pinfo, tvb, offset, erldp_tree);
1156
0
      }
1157
0
      break;
1158
1159
0
    case VERSION_MAGIC:
1160
0
      next_tvb = tvb_new_subset_length(tvb, offset, 4 + msg_len - offset);
1161
0
      dissect_etf_pdu(next_tvb, pinfo, erldp_tree, "DistributionHeader");
1162
0
     break;
1163
1164
0
    default:
1165
0
      proto_tree_add_item(erldp_tree, hf_erldp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1166
0
      offset++;
1167
0
      col_set_str(pinfo->cinfo, COL_INFO, "unknown header format");
1168
0
  }
1169
1170
0
  return tvb_captured_length(tvb);
1171
0
}
1172
1173
/*--- get_erldp_pdu_len -------------------------------------------------*/
1174
static unsigned get_erldp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
1175
                               int offset, void *data _U_)
1176
0
{
1177
0
  if (is_handshake(tvb, offset))
1178
0
    return 2 + tvb_get_ntohs(tvb, offset);
1179
1180
0
  return 4 + tvb_get_ntohl(tvb, offset);
1181
0
}
1182
1183
/*--- dissect_erldp -------------------------------------------------*/
1184
static int
1185
0
dissect_erldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) {
1186
0
  tcp_dissect_pdus(tvb, pinfo, tree,
1187
0
                   erldp_desegment,    /* desegment or not   */
1188
0
                    4,               /* fixed-length part of the PDU */
1189
0
                   get_erldp_pdu_len,  /* routine to get the length of the PDU */
1190
0
                   dissect_erldp_pdu, data); /* routine to dissect a PDU */
1191
0
  return tvb_captured_length(tvb);
1192
0
}
1193
1194
/*--- proto_register_erldp ----------------------------------------------*/
1195
16
void proto_register_erldp(void) {
1196
  /* module_t *erldp_module; */
1197
1198
  /* List of fields */
1199
16
  static hf_register_info hf[] = {
1200
    /*--- Handshake fields ---*/
1201
16
    { &hf_erldp_length_2, { "Length", "erldp.len",
1202
16
                        FT_UINT16, BASE_DEC, NULL, 0x0,
1203
16
                        "Message Length", HFILL}},
1204
16
    { &hf_etf_version_magic, { "VERSION_MAGIC", "erldp.version_magic",
1205
16
                        FT_UINT8, BASE_DEC, NULL, 0x0,
1206
16
                        NULL, HFILL}},
1207
16
    { &hf_erldp_tag,  { "Tag", "erldp.tag",
1208
16
                        FT_CHAR, BASE_HEX, NULL, 0x0,
1209
16
                        NULL, HFILL}},
1210
16
    { &hf_erldp_type, { "Type", "erldp.type",
1211
16
                        FT_UINT8, BASE_DEC, NULL, 0x0,
1212
16
                        NULL, HFILL}},
1213
16
    { &hf_erldp_version, { "Version", "erldp.version",
1214
16
                        FT_UINT16, BASE_DEC, VALS(epmd_version_vals), 0x0,
1215
16
                        NULL, HFILL}},
1216
16
    { &hf_erldp_flags_v5, { "Flags", "erldp.flags_v5",
1217
16
                        FT_UINT32, BASE_HEX, NULL, 0x0,
1218
16
                        NULL, HFILL}},
1219
16
    { &hf_erldp_flags_v6, { "Flags", "erldp.flags_v6",
1220
16
                        FT_UINT64, BASE_HEX, NULL, 0x0,
1221
16
                        NULL, HFILL}},
1222
16
    { &hf_erldp_flags_published, { "Published", "erldp.flags.published",
1223
16
                        FT_BOOLEAN, 64, NULL, 0x1,
1224
16
                        NULL, HFILL }},
1225
16
    { &hf_erldp_flags_atom_cache, { "Atom Cache", "erldp.flags.atom_cache",
1226
16
                        FT_BOOLEAN, 64, NULL, 0x2,
1227
16
                        NULL, HFILL }},
1228
16
    { &hf_erldp_flags_extended_references, { "Extended References", "erldp.flags.extended_references",
1229
16
                        FT_BOOLEAN, 64, NULL, 0x4,
1230
16
                        NULL, HFILL }},
1231
16
    { &hf_erldp_flags_dist_monitor, { "Dist Monitor", "erldp.flags.dist_monitor",
1232
16
                        FT_BOOLEAN, 64, NULL, 0x8,
1233
16
                        NULL, HFILL }},
1234
16
    { &hf_erldp_flags_fun_tags, { "Fun Tags", "erldp.flags.fun_tags",
1235
16
                        FT_BOOLEAN, 64, NULL, 0x10,
1236
16
                        NULL, HFILL }},
1237
16
    { &hf_erldp_flags_dist_monitor_name, { "Dist Monitor Name", "erldp.flags.dist_monitor_name",
1238
16
                        FT_BOOLEAN, 64, NULL, 0x20,
1239
16
                        NULL, HFILL }},
1240
16
    { &hf_erldp_flags_hidden_atom_cache, { "Hidden Atom Cache", "erldp.flags.hidden_atom_cache",
1241
16
                        FT_BOOLEAN, 64, NULL, 0x40,
1242
16
                        NULL, HFILL }},
1243
16
    { &hf_erldp_flags_new_fun_tags, { "New Fun Tags", "erldp.flags.new_fun_tags",
1244
16
                        FT_BOOLEAN, 64, NULL, 0x80,
1245
16
                        NULL, HFILL }},
1246
16
    { &hf_erldp_flags_extended_pids_ports, { "Extended Pids Ports", "erldp.flags.extended_pids_ports",
1247
16
                        FT_BOOLEAN, 64, NULL, 0x100,
1248
16
                        NULL, HFILL }},
1249
16
    { &hf_erldp_flags_export_ptr_tag, { "Export PTR Tag", "erldp.flags.export_ptr_tag",
1250
16
                        FT_BOOLEAN, 64, NULL, 0x200,
1251
16
                        NULL, HFILL }},
1252
16
    { &hf_erldp_flags_bit_binaries, { "Bit Binaries", "erldp.flags.bit_binaries",
1253
16
                        FT_BOOLEAN, 64, NULL, 0x400,
1254
16
                        NULL, HFILL }},
1255
16
    { &hf_erldp_flags_new_floats, { "New Floats", "erldp.flags.new_floats",
1256
16
                        FT_BOOLEAN, 64, NULL, 0x800,
1257
16
                        NULL, HFILL }},
1258
16
    { &hf_erldp_flags_unicode_io, { "Unicode IO", "erldp.flags.unicode_io",
1259
16
                        FT_BOOLEAN, 64, NULL, 0x1000,
1260
16
                        NULL, HFILL }},
1261
16
    { &hf_erldp_flags_dist_hdr_atom_cache, { "Dist HDR Atom Cache", "erldp.flags.dist_hdr_atom_cache",
1262
16
                        FT_BOOLEAN, 64, NULL, 0x2000,
1263
16
                        NULL, HFILL }},
1264
16
    { &hf_erldp_flags_small_atom_tags, { "Small Atom Tags", "erldp.flags.small_atom_tags",
1265
16
                        FT_BOOLEAN, 64, NULL, 0x4000,
1266
16
                        NULL, HFILL }},
1267
16
    { &hf_erldp_flags_ets_compressed, { "ETS Compressed", "erldp.flags.ets_compressed",
1268
16
                        FT_BOOLEAN, 64, NULL, 0x8000,
1269
16
                        NULL, HFILL }},
1270
16
    { &hf_erldp_flags_utf8_atoms, { "UTF8 Atoms", "erldp.flags.utf8_atoms",
1271
16
                        FT_BOOLEAN, 64, NULL, 0x10000,
1272
16
                        NULL, HFILL }},
1273
16
    { &hf_erldp_flags_map_tag, { "Map Tag", "erldp.flags.map_tag",
1274
16
                        FT_BOOLEAN, 64, NULL, 0x20000,
1275
16
                        NULL, HFILL }},
1276
16
    { &hf_erldp_flags_big_creation, { "Big Creation", "erldp.flags.big_creation",
1277
16
                        FT_BOOLEAN, 64, NULL, 0x40000,
1278
16
                        NULL, HFILL }},
1279
16
    { &hf_erldp_flags_send_sender, { "Send Sender", "erldp.flags.send_sender",
1280
16
                        FT_BOOLEAN, 64, NULL, 0x80000,
1281
16
                        NULL, HFILL }},
1282
16
    { &hf_erldp_flags_big_seqtrace_labels, { "Big Seqtrace Labels", "erldp.flags.big_seqtrace_labels",
1283
16
                        FT_BOOLEAN, 64, NULL, 0x100000,
1284
16
                        NULL, HFILL }},
1285
16
    { &hf_erldp_flags_pending_connect, { "Pending Connect", "erldp.flags.pending_connect",
1286
16
                        FT_BOOLEAN, 64, NULL, 0x200000,
1287
16
                        NULL, HFILL }},
1288
16
    { &hf_erldp_flags_exit_payload, { "Exit Payload", "erldp.flags.exit_payload",
1289
16
                        FT_BOOLEAN, 64, NULL, 0x400000,
1290
16
                        NULL, HFILL }},
1291
16
    { &hf_erldp_flags_fragments, { "Fragments", "erldp.flags.fragments",
1292
16
                        FT_BOOLEAN, 64, NULL, 0x800000,
1293
16
                        NULL, HFILL }},
1294
16
    { &hf_erldp_flags_handshake_23, { "Handshake 23", "erldp.flags.handshake_23",
1295
16
                        FT_BOOLEAN, 64, NULL, 0x1000000,
1296
16
                        NULL, HFILL }},
1297
16
    { &hf_erldp_flags_unlink_id, { "Unlink Id", "erldp.flags.unlink_id",
1298
16
                        FT_BOOLEAN, 64, NULL, 0x2000000,
1299
16
                        NULL, HFILL }},
1300
16
    { &hf_erldp_flags_mandatory_25_digest, { "Mandatory 25 Digest", "erldp.flags.mandatory_25_digest",
1301
16
                        FT_BOOLEAN, 64, NULL, 0x4000000,
1302
16
                        NULL, HFILL }},
1303
16
    { &hf_erldp_flags_reserved, { "Reserved", "erldp.flags.reserved",
1304
16
                        FT_UINT64, BASE_DEC, NULL, 0xf8000000,
1305
16
                        NULL, HFILL }},
1306
16
    { &hf_erldp_flags_spawn, { "Spawn", "erldp.flags.spawn",
1307
16
                        FT_BOOLEAN, 64, NULL, 1ULL << 32,
1308
16
                        NULL, HFILL }},
1309
16
    { &hf_erldp_flags_name_me, { "Name ME", "erldp.flags.name_me",
1310
16
                        FT_BOOLEAN, 64, NULL, 1ULL << 33,
1311
16
                        NULL, HFILL }},
1312
16
    { &hf_erldp_flags_v4_nc, { "V4 NC", "erldp.flags.v4_nc",
1313
16
                        FT_BOOLEAN, 64, NULL, 1ULL << 34,
1314
16
                        NULL, HFILL }},
1315
16
    { &hf_erldp_flags_alias, { "Alias", "erldp.flags.alias",
1316
16
                        FT_BOOLEAN, 64, NULL, 1ULL << 35,
1317
16
                        NULL, HFILL }},
1318
16
    { &hf_erldp_flags_local_ext, { "Local Ext", "erldp.flags.local_ext",
1319
16
                        FT_BOOLEAN, 64, NULL, 1ULL << 36,
1320
16
                        NULL, HFILL }},
1321
16
    { &hf_erldp_flags_altact_sig, { "AltAct Sig", "erldp.flags.altact_sig",
1322
16
                        FT_BOOLEAN, 64, NULL, 1ULL << 37,
1323
16
                        NULL, HFILL }},
1324
16
    { &hf_erldp_flags_native_records, { "Native Records", "erldp.flags.native_records",
1325
16
                        FT_BOOLEAN, 64, NULL, 1ULL << 38,
1326
16
                        NULL, HFILL }},
1327
16
    { &hf_erldp_flags_spare, { "Spare", "erldp.flags.spare",
1328
16
                        FT_UINT64, BASE_DEC, NULL,  ~(0ULL) << 39,
1329
16
                        NULL, HFILL }},
1330
16
    { &hf_erldp_flags_high, { "Flags High", "erldp.flags_high",
1331
16
                        FT_UINT32, BASE_HEX, NULL, 0x0,
1332
16
                        "The flags above bit 31", HFILL}},
1333
16
    { &hf_erldp_flags_high_spawn, { "Spawn", "erldp.flags.spawn",
1334
16
                        FT_BOOLEAN, 32, NULL, 0x00000001,
1335
16
                        NULL, HFILL }},
1336
16
    { &hf_erldp_flags_high_name_me, { "Name ME", "erldp.flags.name_me",
1337
16
                        FT_BOOLEAN, 32, NULL, 0x00000002,
1338
16
                        NULL, HFILL }},
1339
16
    { &hf_erldp_flags_high_v4_nc, { "V4 NC", "erldp.flags.v4_nc",
1340
16
                        FT_BOOLEAN, 32, NULL, 0x00000004,
1341
16
                        NULL, HFILL }},
1342
16
    { &hf_erldp_flags_high_alias, { "Alias", "erldp.flags.alias",
1343
16
                        FT_BOOLEAN, 32, NULL, 0x00000008,
1344
16
                        NULL, HFILL }},
1345
16
    { &hf_erldp_flags_high_local_ext, { "Local Ext", "erldp.flags.local_ext",
1346
16
                        FT_BOOLEAN, 32, NULL, 0x00000010,
1347
16
                        NULL, HFILL }},
1348
16
    { &hf_erldp_flags_high_altact_sig, { "AltAct Sig", "erldp.flags.altact_sig",
1349
16
                        FT_BOOLEAN, 32, NULL, 0x00000020,
1350
16
                        NULL, HFILL }},
1351
16
    { &hf_erldp_flags_high_native_records, { "Native Records", "erldp.flags.native_records",
1352
16
                        FT_BOOLEAN, 32, NULL, 0x00000040,
1353
16
                        NULL, HFILL }},
1354
16
    { &hf_erldp_flags_high_spare, { "Spare", "erldp.flags.spare",
1355
16
                        FT_UINT32, BASE_DEC, NULL, 0xffffff80,
1356
16
                        NULL, HFILL }},
1357
16
    { &hf_erldp_creation, { "Creation", "erldp.creation",
1358
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1359
16
                        NULL, HFILL}},
1360
16
    { &hf_erldp_challenge, { "Challenge", "erldp.challenge",
1361
16
                        FT_UINT32, BASE_HEX, NULL, 0x0,
1362
16
                        NULL, HFILL}},
1363
16
    { &hf_erldp_digest, { "Digest", "erldp.digest",
1364
16
                        FT_BYTES, BASE_NONE, NULL, 0x0,
1365
16
                        NULL, HFILL}},
1366
16
    { &hf_erldp_nlen, { "Name Length", "erldp.nlen",
1367
16
                        FT_UINT16, BASE_DEC, NULL, 0x0,
1368
16
                        NULL, HFILL}},
1369
16
    { &hf_erldp_name, { "Name", "erldp.name",
1370
16
                        FT_STRING, BASE_NONE, NULL, 0x0,
1371
16
                        NULL, HFILL}},
1372
16
    { &hf_erldp_status, { "Status", "erldp.status",
1373
16
                        FT_STRING, BASE_NONE, NULL, 0x0,
1374
16
                        NULL, HFILL}},
1375
16
    { &hf_erldp_sequence_id, { "Sequence Id", "erldp.sequence_id",
1376
16
                        FT_UINT64, BASE_HEX, NULL, 0x0,
1377
16
                        NULL, HFILL}},
1378
16
    { &hf_erldp_fragment_id, { "Fragment Id", "erldp.fragment_id",
1379
16
                        FT_UINT64, BASE_HEX, NULL, 0x0,
1380
16
                        NULL, HFILL}},
1381
16
    { &hf_erldp_num_atom_cache_refs, { "NumberOfAtomCacheRefs", "erldp.num_atom_cache_refs",
1382
16
                        FT_UINT8, BASE_DEC, NULL, 0x0,
1383
16
                        NULL, HFILL}},
1384
16
    { &hf_erldp_etf_flags, { "Flags", "erldp.etf_flags",
1385
16
                        FT_BYTES, BASE_NONE, NULL, 0x0,
1386
16
                        NULL, HFILL}},
1387
16
    { &hf_erldp_internal_segment_index, { "InternalSegmentIndex", "erldp.internal_segment_index",
1388
16
                        FT_UINT8, BASE_DEC, NULL, 0x0,
1389
16
                        NULL, HFILL}},
1390
16
    { &hf_erldp_atom_length, { "Length", "erldp.atom_length",
1391
16
                        FT_UINT8, BASE_DEC, NULL, 0x0,
1392
16
                        NULL, HFILL}},
1393
16
    { &hf_erldp_atom_length2, { "Length", "erldp.atom_length",
1394
16
                        FT_UINT16, BASE_DEC, NULL, 0x0,
1395
16
                        NULL, HFILL}},
1396
16
    { &hf_erldp_atom_text, { "AtomText", "erldp.atom_text",
1397
16
                        FT_STRING, BASE_NONE, NULL, 0x0,
1398
16
                        NULL, HFILL}},
1399
16
    { &hf_erldp_string_ext_len, { "Len", "erldp.string_ext_len",
1400
16
                        FT_UINT16, BASE_DEC, NULL, 0x0,
1401
16
                        NULL, HFILL}},
1402
16
    { &hf_erldp_string_ext, { "String", "erldp.string_ext",
1403
16
                        FT_STRING, BASE_SHOW_ASCII_PRINTABLE, NULL, 0x0,
1404
16
                        NULL, HFILL}},
1405
16
    { &hf_erldp_atom_cache_ref, { "AtomCacheReferenceIndex", "erldp.atom_cache_ref",
1406
16
                        FT_UINT8, BASE_DEC, NULL, 0x0,
1407
16
                        NULL, HFILL}},
1408
16
    { &hf_erldp_small_int_ext, { "Int", "erldp.small_int_ext",
1409
16
                        FT_UINT8, BASE_DEC, NULL, 0x0,
1410
16
                        NULL, HFILL}},
1411
16
    { &hf_erldp_int_ext, { "Int", "erldp.int_ext",
1412
16
                        FT_INT32, BASE_DEC, NULL, 0x0,
1413
16
                        NULL, HFILL}},
1414
16
    { &hf_erldp_small_big_ext_len, { "Len", "erldp.small_big_ext_len",
1415
16
                        FT_UINT8, BASE_DEC, NULL, 0x0,
1416
16
                        NULL, HFILL}},
1417
16
    { &hf_erldp_large_big_ext_len, { "Len", "erldp.large_big_ext_len",
1418
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1419
16
                        NULL, HFILL}},
1420
16
    { &hf_erldp_big_ext_int, { "Int", "erldp.big_ext_int",
1421
16
                        FT_UINT64, BASE_DEC, NULL, 0x0,
1422
16
                        NULL, HFILL}},
1423
16
    { &hf_erldp_big_ext_str, { "Int", "erldp.big_ext_str",
1424
16
                        FT_STRING, BASE_NONE, NULL, 0x0,
1425
16
                        NULL, HFILL}},
1426
16
    { &hf_erldp_big_ext_bytes, { "Int", "erldp.big_ext_bytes",
1427
16
                        FT_BYTES, BASE_NONE, NULL, 0x0,
1428
16
                        NULL, HFILL}},
1429
16
    { &hf_erldp_float_ext, { "Float", "erldp.float_ext",
1430
16
                        FT_STRINGZ, BASE_NONE, NULL, 0x0,
1431
16
                        NULL, HFILL}},
1432
16
    { &hf_erldp_new_float_ext, { "Float", "erldp.new_float_ext",
1433
16
                        FT_DOUBLE, BASE_NONE, NULL, 0x0,
1434
16
                        NULL, HFILL}},
1435
16
    { &hf_erldp_port_ext_id, { "ID", "erldp.port_ext.id",
1436
16
                        FT_UINT32, BASE_HEX, NULL, 0x0,
1437
16
                        NULL, HFILL}},
1438
16
    { &hf_erldp_port_ext_v4_id, { "ID", "erldp.port_ext.v4_id",
1439
16
                        FT_UINT64, BASE_HEX, NULL, 0x0,
1440
16
                        NULL, HFILL}},
1441
16
    { &hf_erldp_port_ext_creation, { "Creation", "erldp.port_ext.creation",
1442
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1443
16
                        NULL, HFILL}},
1444
16
    { &hf_erldp_pid_ext_id, { "ID", "erldp.pid_ext.id",
1445
16
                        FT_UINT32, BASE_HEX, NULL, 0x0,
1446
16
                        NULL, HFILL}},
1447
16
    { &hf_erldp_pid_ext_serial, { "Serial", "erldp.pid_ext.serial",
1448
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1449
16
                        NULL, HFILL}},
1450
16
    { &hf_erldp_pid_ext_creation, { "Creation", "erldp.pid_ext.creation",
1451
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1452
16
                        NULL, HFILL}},
1453
16
    { &hf_erldp_list_ext_len, { "Len", "erldp.list_ext.len",
1454
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1455
16
                        NULL, HFILL}},
1456
16
    { &hf_erldp_map_ext_len, { "Len", "erldp.map_ext.len",
1457
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1458
16
                        NULL, HFILL}},
1459
16
    { &hf_erldp_binary_ext_len, { "Len", "erldp.binary_ext.len",
1460
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1461
16
                        NULL, HFILL}},
1462
16
    { &hf_erldp_binary_ext_bits, { "Num bits in last byte", "erldp.binary_ext.bits",
1463
16
                        FT_UINT8, BASE_DEC, NULL, 0x0,
1464
16
                        NULL, HFILL}},
1465
16
    { &hf_erldp_binary_ext, { "Binary", "erldp.binary_ext",
1466
16
                        FT_BYTES, BASE_SHOW_ASCII_PRINTABLE, NULL, 0x0,
1467
16
                        NULL, HFILL}},
1468
16
    { &hf_erldp_new_ref_ext_len, { "Len", "erldp.new_ref_ext.len",
1469
16
                        FT_UINT16, BASE_DEC, NULL, 0x0,
1470
16
                        NULL, HFILL}},
1471
16
    { &hf_erldp_new_ref_ext_creation, { "Creation", "erldp.new_ref_ext.creation",
1472
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1473
16
                        NULL, HFILL}},
1474
16
    { &hf_erldp_new_ref_ext_id, { "ID", "erldp.new_ref_ext.id",
1475
16
                        FT_UINT32, BASE_HEX, NULL, 0x0,
1476
16
                        NULL, HFILL}},
1477
16
    { &hf_erldp_fun_ext_num_free, { "Num Free", "erldp.fun_ext.num_free",
1478
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1479
16
                        NULL, HFILL}},
1480
16
    { &hf_erldp_new_fun_ext_size, { "Size", "erldp.new_fun_ext.size",
1481
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1482
16
                        NULL, HFILL}},
1483
16
    { &hf_erldp_new_fun_ext_arity, { "Arity", "erldp.new_fun_ext.arity",
1484
16
                        FT_UINT8, BASE_DEC, NULL, 0x0,
1485
16
                        NULL, HFILL}},
1486
16
    { &hf_erldp_new_fun_ext_uniq, { "Uniq", "erldp.new_fun_ext.uniq",
1487
16
                        FT_BYTES, BASE_NONE, NULL, 0x0,
1488
16
                        NULL, HFILL}},
1489
16
    { &hf_erldp_new_fun_ext_index, { "Index", "erldp.new_fun_ext.index",
1490
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1491
16
                        NULL, HFILL}},
1492
16
    { &hf_erldp_new_fun_ext_num_free, { "Num Free", "erldp.new_fun_ext.num_free",
1493
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1494
16
                        NULL, HFILL}},
1495
16
    { &hf_erldp_ref_ext_id, { "ID", "erldp.ref_ext.id",
1496
16
                        FT_UINT32, BASE_HEX, NULL, 0x0,
1497
16
                        NULL, HFILL}},
1498
16
    { &hf_erldp_local_ext_hash, { "Hash", "erldp.local_ext.hash",
1499
16
                        FT_UINT32, BASE_HEX, NULL, 0x0,
1500
16
                        "Checked by the decoder to match the encoder", HFILL}},
1501
16
    { &hf_erldp_local_ext_data, { "Local Data", "erldp.local_ext.data",
1502
16
                        FT_BYTES, BASE_NONE, NULL, 0x0,
1503
16
                        "Terms in a format known only to the node that encoded them", HFILL}},
1504
16
    { &hf_erldp_undecoded, { "Undecoded Data", "erldp.undecoded",
1505
16
                        FT_BYTES, BASE_NONE, NULL, 0x0,
1506
16
                        NULL, HFILL}},
1507
16
    { &hf_erldp_record_ext_num_fields, { "Num Fields", "erldp.record_ext.num_fields",
1508
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1509
16
                        NULL, HFILL}},
1510
16
    { &hf_erldp_record_ext_flags, { "Flags", "erldp.record_ext.flags",
1511
16
                        FT_UINT8, BASE_HEX, NULL, 0x0,
1512
16
                        NULL, HFILL}},
1513
16
    { &hf_erldp_record_ext_flags_exported, { "Exported", "erldp.record_ext.flags.exported",
1514
16
                        FT_BOOLEAN, 8, NULL, 0x01,
1515
16
                        "The record is exported from its module", HFILL}},
1516
16
    { &hf_erldp_record_ext_flags_reserved, { "Reserved", "erldp.record_ext.flags.reserved",
1517
16
                        FT_UINT8, BASE_HEX, NULL, 0xfe,
1518
16
                        NULL, HFILL}},
1519
16
    { &hf_erldp_altact_flags, { "AltAct Flags", "erldp.altact_flags",
1520
16
                        FT_UINT8, BASE_HEX, NULL, 0x0,
1521
16
                        "ALTACT_SIG_SEND flags", HFILL}},
1522
16
    { &hf_erldp_altact_flags_prio, { "Priority", "erldp.altact_flags.prio",
1523
16
                        FT_BOOLEAN, 8, NULL, ALTACT_SIG_FLG_PRIO,
1524
16
                        "This is a priority signal", HFILL}},
1525
16
    { &hf_erldp_altact_flags_token, { "Token", "erldp.altact_flags.token",
1526
16
                        FT_BOOLEAN, 8, NULL, ALTACT_SIG_FLG_TOKEN,
1527
16
                        "A sequential trace token follows To", HFILL}},
1528
16
    { &hf_erldp_altact_flags_alias, { "Alias", "erldp.altact_flags.alias",
1529
16
                        FT_BOOLEAN, 8, NULL, ALTACT_SIG_FLG_ALIAS,
1530
16
                        "To is a process alias (a reference)", HFILL}},
1531
16
    { &hf_erldp_altact_flags_name, { "Name", "erldp.altact_flags.name",
1532
16
                        FT_BOOLEAN, 8, NULL, ALTACT_SIG_FLG_NAME,
1533
16
                        "To is a registered name (an atom)", HFILL}},
1534
16
    { &hf_erldp_altact_flags_exit, { "Exit", "erldp.altact_flags.exit",
1535
16
                        FT_BOOLEAN, 8, NULL, ALTACT_SIG_FLG_EXIT,
1536
16
                        "The signal is an exit signal, not a message", HFILL}},
1537
1538
    /*---  ---*/
1539
16
    { &hf_erldp_length_4, { "Length", "erldp.len",
1540
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1541
16
                        "Message Length", HFILL}},
1542
1543
    /*--- ETF  ---*/
1544
16
    { &hf_etf_tag,    { "Tag", "erldp.etf_tag",
1545
16
                        FT_UINT8, BASE_DEC, VALS(etf_tag_vals), 0x0,
1546
16
                        NULL, HFILL}},
1547
16
    { &hf_etf_dist_header_tag, { "Tag", "erldp.etf_header_tag",
1548
16
                        FT_UINT8, BASE_DEC, VALS(etf_header_tag_vals), 0x0,
1549
16
                        NULL, HFILL}},
1550
1551
16
    { &hf_etf_dist_header_new_cache,    { "NewCacheEntryFlag", "erldp.dist_header.new_cache",
1552
16
                        FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x08,
1553
16
                        NULL, HFILL}},
1554
1555
16
    { &hf_etf_dist_header_segment_index,    { "SegmentIndex", "erldp.dist_header.segment_index",
1556
16
                        FT_UINT8, BASE_DEC, NULL, 0x7,
1557
16
                        NULL, HFILL}},
1558
1559
16
    { &hf_etf_dist_header_long_atoms,    { "LongAtoms", "erldp.dist_header.long_atoms",
1560
16
                        FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x12,
1561
16
                        NULL, HFILL}},
1562
1563
16
    { &hf_etf_arity4, { "Arity", "erldp.arity",
1564
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1565
16
                        NULL, HFILL}},
1566
1567
16
    { &hf_etf_arity, { "Arity", "erldp.arity",
1568
16
                        FT_UINT8, BASE_DEC, NULL, 0x0,
1569
16
                        NULL, HFILL}},
1570
1571
16
    { &hf_etf_fragments, { "Message fragments", "erldp.dist.fragments",
1572
16
                        FT_NONE, BASE_NONE, NULL, 0x0, NULL,
1573
16
                        HFILL }},
1574
1575
16
    { &hf_etf_fragment, { "Message fragment", "erldp.dist.fragment",
1576
16
                        FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1577
16
                        NULL, HFILL }},
1578
1579
16
    { &hf_etf_fragment_overlap, { "Message fragment overlap", "erldp.dist.fragment.overlap",
1580
16
                        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1581
16
                        NULL, HFILL }},
1582
1583
16
    { &hf_etf_fragment_overlap_conflicts, { "Message fragment overlapping with conflicting data",
1584
16
                                                            "erldp.dist.fragment.overlap.conflicts",
1585
16
                        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1586
16
                        NULL, HFILL }},
1587
1588
16
    { &hf_etf_fragment_multiple_tails, { "Message has multiple tail fragments",
1589
16
                                                         "erldp.dist.fragment.multiple_tails",
1590
16
                        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1591
16
                        NULL, HFILL }},
1592
1593
16
    { &hf_etf_fragment_too_long_fragment, { "Message fragment too long", "erldp.dist.fragment.too_long_fragment",
1594
16
                        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1595
16
                        NULL, HFILL }},
1596
1597
16
    { &hf_etf_fragment_error, { "Message defragmentation error", "erldp.dist.fragment.error",
1598
16
                        FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1599
16
                        NULL, HFILL }},
1600
1601
16
    { &hf_etf_fragment_count, { "Message fragment count", "erldp.dist.fragment.count",
1602
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1603
16
                        NULL, HFILL }},
1604
1605
16
    { &hf_etf_reassembled_in, { "Reassembled in", "erldp.dist.reassembled.in",
1606
16
                        FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1607
16
                        NULL, HFILL }},
1608
1609
16
    { &hf_etf_reassembled_length, { "Reassembled length", "erldp.dist.reassembled.length",
1610
16
                        FT_UINT32, BASE_DEC, NULL, 0x0,
1611
16
                        NULL, HFILL }},
1612
1613
16
    { &hf_etf_reassembled_data, { "Reassembled data", "erldp.dist.reassembled.data",
1614
16
                        FT_BYTES, BASE_NONE, NULL, 0x0,
1615
16
                        NULL, HFILL }},
1616
16
  };
1617
1618
  /* List of subtrees */
1619
16
  static int *ett[] = {
1620
16
    &ett_erldp,
1621
16
    &ett_erldp_flags,
1622
16
    &ett_etf,
1623
16
    &ett_etf_flags,
1624
16
    &ett_etf_acrs,
1625
16
    &ett_etf_acr,
1626
16
    &ett_etf_tmp,
1627
16
    &ett_etf_altact_flags,
1628
16
    &ett_etf_record_flags,
1629
16
    &ett_etf_fragment,
1630
16
    &ett_etf_fragments,
1631
16
  };
1632
1633
16
  static ei_register_info ei[] = {
1634
16
    { &ei_erldp_unknown_tag, { "erldp.unknown_tag", PI_UNDECODED, PI_WARN,
1635
16
                        "Unknown term tag; the rest of the message is not decoded", EXPFILL }},
1636
16
  };
1637
1638
16
  expert_module_t *expert_erldp;
1639
1640
  /* Register protocol and dissector */
1641
16
  proto_erldp = proto_register_protocol("Erlang Distribution Protocol", "ErlDP", "erldp");
1642
16
  reassembly_table_register(&erldp_reassembly_table,
1643
16
                          &addresses_reassembly_table_functions);
1644
1645
16
  erldp_handle = register_dissector("erldp", dissect_erldp, proto_erldp);
1646
1647
  /* Register fields and subtrees */
1648
16
  proto_register_field_array(proto_erldp, hf, array_length(hf));
1649
16
  proto_register_subtree_array(ett, array_length(ett));
1650
16
  expert_erldp = expert_register_protocol(proto_erldp);
1651
16
  expert_register_field_array(expert_erldp, ei, array_length(ei));
1652
1653
16
}
1654
1655
/*--- proto_reg_handoff_erldp -------------------------------------------*/
1656
16
void proto_reg_handoff_erldp(void) {
1657
1658
16
  dissector_add_for_decode_as_with_preference("tcp.port", erldp_handle);
1659
16
}
1660
1661
/*
1662
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1663
 *
1664
 * Local Variables:
1665
 * c-basic-offset: 2
1666
 * tab-width: 8
1667
 * indent-tabs-mode: nil
1668
 * End:
1669
 *
1670
 * ex: set shiftwidth=2 tabstop=8 expandtab:
1671
 * :indentSize=2:tabSize=8:noTabs=true:
1672
 */