Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-epmd.c
Line
Count
Source
1
/* packet-epmd.c
2
 * dissector for EPMD (Erlang Port Mapper Daemon) messages;
3
 * this are the messages sent between Erlang nodes and
4
 * the empd process.
5
 * The message formats are derived from the
6
 * lib/kernel/src/erl_epmd.* files as part of the Erlang
7
 * distribution available from http://www.erlang.org/
8
 *
9
 * (c) 2007 Joost Yervante Damad <joost[AT]teluna.org>
10
 *
11
 * Wireshark - Network traffic analyzer
12
 * By Gerald Combs <gerald[AT]wireshark.org>
13
 * Copyright 1998 Gerald Combs
14
 *
15
 * Copied from packet-time.c
16
 *
17
 * SPDX-License-Identifier: GPL-2.0-or-later
18
 */
19
20
#include "config.h"
21
22
#include <epan/packet.h>
23
#include <epan/expert.h>
24
#include <epan/conversation.h>
25
26
#include "packet-epmd.h"
27
28
void proto_register_epmd(void);
29
void proto_reg_handoff_epmd(void);
30
31
static int proto_epmd;
32
static int hf_epmd_len;
33
static int hf_epmd_type;
34
static int hf_epmd_port_no;
35
static int hf_epmd_node_type;
36
static int hf_epmd_protocol;
37
static int hf_epmd_dist_high;
38
static int hf_epmd_dist_low;
39
static int hf_epmd_name_len;
40
static int hf_epmd_name;
41
static int hf_epmd_elen;
42
static int hf_epmd_edata;
43
static int hf_epmd_node_container;
44
static int hf_epmd_node_name;
45
static int hf_epmd_node_port;
46
static int hf_epmd_result;
47
static int hf_epmd_creation;
48
static int hf_epmd_creation2;
49
50
static int ett_epmd;
51
static int ett_epmd_node;
52
53
static expert_module_t* expert_epmd;
54
static expert_field ei_epmd_malformed_names_line;
55
56
static dissector_handle_t epmd_handle;
57
58
/* Other dissectors */
59
static dissector_handle_t edp_handle;
60
61
32
#define EPMD_PORT 4369
62
63
/* Definitions of message codes */
64
0
#define EPMD_ALIVE_REQ     'a'
65
1
#define EPMD_ALIVE_OK_RESP 'Y'
66
1
#define EPMD_PORT_REQ      'p'
67
3
#define EPMD_NAMES_REQ     'n'
68
#define EPMD_DUMP_REQ      'd'
69
#define EPMD_KILL_REQ      'k'
70
#define EPMD_STOP_REQ      's'
71
/* New epmd messages */
72
0
#define EPMD_ALIVE2_REQ    'x' /* 120 */
73
3
#define EPMD_PORT2_REQ     'z' /* 122 */
74
1
#define EPMD_ALIVE2_RESP   'y' /* 121 */
75
2
#define EPMD_PORT2_RESP    'w' /* 119 */
76
2
#define EPMD_ALIVE2_X_RESP 'v' /* 118 - Extended response for highvsn >= 6 */
77
78
static const value_string message_types[] = {
79
    { EPMD_ALIVE_REQ    , "EPMD_ALIVE_REQ"     },
80
    { EPMD_ALIVE_OK_RESP, "EPMD_ALIVE_OK_RESP" },
81
    { EPMD_PORT_REQ     , "EPMD_PORT_REQ"      },
82
    { EPMD_NAMES_REQ    , "EPMD_NAMES_REQ"     },
83
    { EPMD_DUMP_REQ     , "EPMD_DUMP_REQ"      },
84
    { EPMD_KILL_REQ     , "EPMD_KILL_REQ"      },
85
    { EPMD_STOP_REQ     , "EPMD_STOP_REQ"      },
86
    { EPMD_ALIVE2_REQ   , "EPMD_ALIVE2_REQ"    },
87
    { EPMD_PORT2_REQ    , "EPMD_PORT2_REQ"     },
88
    { EPMD_ALIVE2_RESP  , "EPMD_ALIVE2_RESP"   },
89
    { EPMD_PORT2_RESP   , "EPMD_PORT2_RESP"    },
90
    { EPMD_ALIVE2_X_RESP, "EPMD_ALIVE2_X_RESP" },
91
    {  0, NULL }
92
};
93
94
static const value_string node_type_vals[] = {
95
    {  72 , "R3 hidden node" },
96
    {  77 , "R3 erlang node" },
97
    { 104 , "R4 hidden node" },
98
    { 109 , "R4 erlang node" },
99
    { 110 , "R6 nodes" },
100
    {  0, NULL }
101
};
102
103
static const value_string protocol_vals[] = {
104
    {  0 , "tcp/ip-v4" },
105
    {  0, NULL }
106
};
107
108
const value_string epmd_version_vals[] = {
109
    {  0 , "R3"     },
110
    {  1 , "R4"     },
111
    {  2 , "R5"     },
112
    {  3 , "R5C"    },
113
    {  4 , "R6 dev" },
114
    {  5 , "R6"     },
115
    {  0, NULL }
116
};
117
118
static void
119
3
dissect_epmd_request(packet_info *pinfo, tvbuff_t *tvb, unsigned offset, proto_tree *tree) {
120
3
    uint8_t       type;
121
3
    uint16_t      name_length = 0;
122
3
    const uint8_t *name        = NULL;
123
124
3
    proto_tree_add_item(tree, hf_epmd_len, tvb, offset, 2, ENC_BIG_ENDIAN);
125
3
    offset += 2;
126
3
    proto_tree_add_item_ret_uint8(tree, hf_epmd_type, tvb, offset, 1, ENC_BIG_ENDIAN, &type);
127
3
    offset++;
128
3
    col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, type, VALS(message_types), "unknown (0x%02X)"));
129
130
3
    switch (type) {
131
0
        case EPMD_ALIVE2_REQ:
132
0
            proto_tree_add_item(tree, hf_epmd_port_no, tvb, offset, 2, ENC_BIG_ENDIAN);
133
0
            offset += 2;
134
0
            proto_tree_add_item(tree, hf_epmd_node_type, tvb, offset, 1, ENC_BIG_ENDIAN);
135
0
            offset++;
136
0
            proto_tree_add_item(tree, hf_epmd_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
137
0
            offset++;
138
0
            proto_tree_add_item(tree, hf_epmd_dist_high, tvb, offset, 2, ENC_BIG_ENDIAN);
139
0
            offset += 2;
140
0
            proto_tree_add_item(tree, hf_epmd_dist_low, tvb, offset, 2, ENC_BIG_ENDIAN);
141
0
            offset += 2;
142
0
            proto_tree_add_item_ret_uint16(tree, hf_epmd_name_len, tvb, offset, 2, ENC_BIG_ENDIAN, &name_length);
143
0
            proto_tree_add_item_ret_string(tree, hf_epmd_name, tvb, offset + 2, name_length, ENC_ASCII|ENC_NA, pinfo->pool, &name);
144
0
            offset += 2 + name_length;
145
0
            if (tvb_reported_length_remaining(tvb, offset) >= 2) {
146
0
                uint16_t elen=0;
147
0
                proto_tree_add_item_ret_uint16(tree, hf_epmd_elen, tvb, offset, 2, ENC_BIG_ENDIAN, &elen);
148
0
                if (elen > 0)
149
0
                    proto_tree_add_item(tree, hf_epmd_edata, tvb, offset + 2, elen, ENC_NA);
150
                /*offset += 2 + elen;*/
151
0
            }
152
0
            break;
153
154
0
        case EPMD_PORT_REQ:
155
1
        case EPMD_PORT2_REQ:
156
1
            name_length = tvb_captured_length_remaining(tvb, offset);
157
1
            proto_tree_add_item_ret_string(tree, hf_epmd_name, tvb, offset, name_length, ENC_ASCII|ENC_NA, pinfo->pool, &name);
158
1
            break;
159
160
0
        case EPMD_ALIVE_REQ:
161
0
            proto_tree_add_item(tree, hf_epmd_port_no, tvb, offset, 2, ENC_BIG_ENDIAN);
162
0
            offset += 2;
163
0
            name_length = tvb_captured_length_remaining(tvb, offset);
164
0
            proto_tree_add_item_ret_string(tree, hf_epmd_name, tvb, offset, name_length, ENC_ASCII|ENC_NA, pinfo->pool, &name);
165
0
            break;
166
167
0
        case EPMD_NAMES_REQ:
168
0
            break;
169
170
3
    }
171
172
3
    if (name) {
173
1
        col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
174
1
    }
175
176
3
}
177
178
static void
179
dissect_epmd_response_names(packet_info *pinfo _U_, tvbuff_t *tvb, unsigned offset, proto_tree *tree)
180
0
{
181
0
    unsigned off = offset;
182
183
0
    unsigned next_off;
184
0
    while (tvb_captured_length_remaining(tvb, off)) {
185
0
        unsigned linelen;
186
0
        tvb_find_line_end_remaining(tvb, off, &linelen, &next_off);
187
0
        proto_item *node_ti = proto_tree_add_item(tree,hf_epmd_node_container, tvb, off, linelen, ENC_NA);
188
0
        proto_tree *node_tree = proto_item_add_subtree(node_ti, ett_epmd_node);
189
190
0
        if (tvb_strneql(tvb, off, "name ", 5) != 0) {
191
0
            off = next_off;
192
0
            expert_add_info_format(pinfo, node_tree, &ei_epmd_malformed_names_line, "Malformed line: expected 'name ' at start");
193
0
            continue;
194
0
        }
195
0
        unsigned name_start = off + 5;
196
197
0
        unsigned name_end;
198
0
        if (!tvb_find_uint8_length(tvb, name_start, linelen - (name_start - off), ' ', &name_end)){
199
0
            off = next_off;
200
0
            expert_add_info_format(pinfo, node_tree, &ei_epmd_malformed_names_line, "Malformed line: missing space after node name");
201
0
            continue;
202
0
        }
203
204
0
        if (tvb_strneql(tvb, name_end, " at port ", 9) != 0) {
205
0
            off = next_off;
206
0
            expert_add_info_format(pinfo, node_tree, &ei_epmd_malformed_names_line, "Malformed line: expected ' at port '");
207
0
            continue;
208
0
        }
209
210
0
        proto_tree_add_item(node_tree, hf_epmd_node_name, tvb, name_start, name_end-name_start, ENC_ASCII);
211
0
        int pos_port = name_end + 9;
212
0
        int port_len = (off + linelen) - pos_port;
213
214
0
        off = next_off; // skip '\n'
215
0
        if (port_len <= 0) {
216
0
            continue;
217
0
        }
218
0
        uint16_t portnum;
219
0
        if (!tvb_get_string_uint16(tvb, pos_port, port_len, ENC_STR_DEC, &portnum, NULL)){
220
0
            expert_add_info_format(pinfo, node_tree, &ei_epmd_malformed_names_line, "Invalid or missing port number");
221
0
            continue;
222
0
        }
223
0
        proto_tree_add_uint(node_tree, hf_epmd_node_port, tvb, pos_port, 2, portnum);
224
0
    }
225
0
}
226
227
static int
228
2
dissect_epmd_response(packet_info *pinfo, tvbuff_t *tvb, unsigned offset, proto_tree *tree) {
229
2
    uint8_t         type, result;
230
2
    uint32_t        port;
231
2
    uint16_t        name_length = 0;
232
2
    const uint8_t  *name        = NULL;
233
2
    conversation_t *conv        = NULL;
234
235
2
    port = tvb_get_ntohl(tvb, offset);
236
2
    if (port == EPMD_PORT) {
237
0
        dissect_epmd_response_names(pinfo, tvb, offset + 4, tree);
238
0
        return 0;
239
0
    }
240
241
2
    proto_tree_add_item_ret_uint8(tree, hf_epmd_type, tvb, offset, 1, ENC_BIG_ENDIAN, &type);
242
2
    offset++;
243
2
    col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, type, VALS(message_types), "unknown (0x%02X)"));
244
245
2
    switch (type) {
246
0
        case EPMD_ALIVE_OK_RESP:
247
0
            proto_tree_add_item_ret_uint8(tree, hf_epmd_result, tvb, offset, 1, ENC_BIG_ENDIAN, &result);
248
0
            offset++;
249
0
            proto_tree_add_item(tree, hf_epmd_creation, tvb, offset, 2, ENC_BIG_ENDIAN);
250
0
            offset += 2;
251
0
            if (!result) {
252
0
                col_append_str(pinfo->cinfo, COL_INFO, " OK");
253
0
            } else {
254
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " ERROR 0x%02X", result);
255
0
            }
256
0
            break;
257
258
0
        case EPMD_ALIVE2_RESP:
259
0
            proto_tree_add_item_ret_uint8(tree, hf_epmd_result, tvb, offset, 1, ENC_BIG_ENDIAN, &result);
260
0
            offset++;
261
0
            if (!result) {
262
0
                proto_tree_add_item(tree, hf_epmd_creation, tvb, offset, 2, ENC_BIG_ENDIAN);
263
0
                offset += 2;
264
0
                col_append_str(pinfo->cinfo, COL_INFO, " OK");
265
0
            } else {
266
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " ERROR 0x%02X", result);
267
0
            }
268
0
            break;
269
270
0
        case EPMD_ALIVE2_X_RESP:
271
0
            proto_tree_add_item_ret_uint8(tree, hf_epmd_result, tvb, offset, 1, ENC_BIG_ENDIAN, &result);
272
0
            offset++;
273
0
            if (!result) {
274
                /* Check remaining length to determine creation field size */
275
0
                int remaining = tvb_reported_length_remaining(tvb, offset);
276
0
                if (remaining >= 4) {
277
0
                    proto_tree_add_item(tree, hf_epmd_creation2, tvb, offset, 4, ENC_BIG_ENDIAN);
278
0
                    offset += 4;
279
0
                } else if (remaining >= 2) {
280
0
                    proto_tree_add_item(tree, hf_epmd_creation, tvb, offset, 2, ENC_BIG_ENDIAN);
281
0
                    offset += 2;
282
0
                }
283
0
                col_append_str(pinfo->cinfo, COL_INFO, " OK");
284
0
            } else {
285
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " ERROR 0x%02X", result);
286
0
            }
287
0
            break;
288
289
0
        case EPMD_PORT2_RESP:
290
0
            proto_tree_add_item_ret_uint8(tree, hf_epmd_result, tvb, offset, 1, ENC_BIG_ENDIAN, &result);
291
0
            offset++;
292
0
            if (!result) {
293
0
                col_append_str(pinfo->cinfo, COL_INFO, " OK");
294
0
            } else {
295
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " ERROR 0x%02X", result);
296
0
                break;
297
0
            }
298
0
            proto_tree_add_item_ret_uint(tree, hf_epmd_port_no, tvb, offset, 2, ENC_BIG_ENDIAN, &port);
299
0
            offset += 2;
300
0
            proto_tree_add_item(tree, hf_epmd_node_type, tvb, offset, 1, ENC_BIG_ENDIAN);
301
0
            offset++;
302
0
            proto_tree_add_item(tree, hf_epmd_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
303
0
            offset++;
304
0
            proto_tree_add_item(tree, hf_epmd_dist_high, tvb, offset, 2, ENC_BIG_ENDIAN);
305
0
            offset += 2;
306
0
            proto_tree_add_item(tree, hf_epmd_dist_low, tvb, offset, 2, ENC_BIG_ENDIAN);
307
0
            offset += 2;
308
0
            proto_tree_add_item_ret_uint16(tree, hf_epmd_name_len, tvb, offset, 2, ENC_BIG_ENDIAN, &name_length);
309
0
            proto_tree_add_item_ret_string(tree, hf_epmd_name, tvb, offset + 2, name_length, ENC_ASCII|ENC_NA, pinfo->pool, &name);
310
0
            offset += 2 + name_length;
311
0
            if (tvb_reported_length_remaining(tvb, offset) >= 2) {
312
0
                uint16_t elen;
313
0
                proto_tree_add_item_ret_uint16(tree, hf_epmd_elen, tvb, offset, 2, ENC_BIG_ENDIAN, &elen);
314
0
                if (elen > 0)
315
0
                    proto_tree_add_item(tree, hf_epmd_edata, tvb, offset + 2, elen, ENC_NA);
316
0
                offset += 2 + elen;
317
0
            }
318
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " %s port=%d", name, port);
319
0
            if (!pinfo->fd->visited) {
320
0
                conv = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, port, 0, NO_PORT2);
321
0
                conversation_set_dissector(conv, edp_handle);
322
0
            }
323
0
            break;
324
2
    }
325
2
    return offset;
326
2
}
327
328
static bool
329
17
check_epmd(tvbuff_t *tvb) {
330
17
    uint8_t type;
331
332
    /* simple heuristic:
333
     *
334
     * just check if the type is one of the EPMD
335
     * command types
336
     *
337
     * It's possible to start checking lengths but imho that
338
     * doesn't bring very much.
339
     */
340
17
    if (tvb_captured_length(tvb) < 3)
341
3
        return false;
342
343
    /* If the first 4 bytes interpreted as uint32_be equal EPMD port (0x00001111),
344
     * this is the 'names' style response that begins with 0x00001111.
345
     * Accept it as EPMD.
346
     */
347
14
    if (tvb_get_ntohl(tvb, 0) == EPMD_PORT)
348
0
        return true;
349
350
14
    type = tvb_get_uint8(tvb, 0);
351
14
    switch (type) {
352
1
        case EPMD_ALIVE_OK_RESP:
353
1
        case EPMD_ALIVE2_RESP:
354
2
        case EPMD_ALIVE2_X_RESP:
355
2
        case EPMD_PORT2_RESP:
356
2
            return true;
357
12
        default:
358
12
            break;
359
14
    }
360
361
12
    type = tvb_get_uint8(tvb, 2);
362
12
    switch (type) {
363
0
        case EPMD_ALIVE_REQ:
364
0
        case EPMD_ALIVE2_REQ:
365
1
        case EPMD_PORT_REQ:
366
2
        case EPMD_PORT2_REQ:
367
3
        case EPMD_NAMES_REQ:
368
3
            return true;
369
9
        default:
370
9
            break;
371
12
    }
372
373
9
    return false;
374
12
}
375
376
static int
377
17
dissect_epmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
378
17
    proto_tree *epmd_tree;
379
17
    proto_item *ti;
380
381
17
    if (!check_epmd(tvb))
382
12
        return 0;
383
384
5
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "EPMD");
385
386
5
    ti = proto_tree_add_item(tree, proto_epmd, tvb, 0, -1, ENC_NA);
387
5
    epmd_tree = proto_item_add_subtree(ti, ett_epmd);
388
389
5
    if (pinfo->match_uint == pinfo->destport) {
390
3
        dissect_epmd_request(pinfo, tvb, 0, epmd_tree);
391
3
    } else {
392
2
        dissect_epmd_response(pinfo, tvb, 0, epmd_tree);
393
2
    }
394
395
5
    return (tvb_captured_length(tvb));
396
17
}
397
398
void
399
proto_register_epmd(void)
400
16
{
401
16
    static hf_register_info hf[] = {
402
16
        { &hf_epmd_len,
403
16
          { "Length", "epmd.len",
404
16
            FT_UINT16, BASE_DEC, NULL, 0x0,
405
16
            "Message Length", HFILL }},
406
407
16
        { &hf_epmd_type,
408
16
          { "Type", "epmd.type",
409
16
            FT_UINT8, BASE_DEC, VALS(message_types), 0x0,
410
16
            "Message Type", HFILL }},
411
412
16
        { &hf_epmd_result,
413
16
          { "Result", "epmd.result",
414
16
            FT_UINT8, BASE_DEC, NULL, 0x0,
415
16
            NULL, HFILL }},
416
417
16
        { &hf_epmd_port_no,
418
16
          { "Port No", "epmd.port_no",
419
16
            FT_UINT16, BASE_DEC, NULL, 0x0,
420
16
            NULL, HFILL }},
421
422
16
        { &hf_epmd_node_type,
423
16
          { "Node Type", "epmd.node_type",
424
16
            FT_UINT8, BASE_DEC, VALS(node_type_vals), 0x0,
425
16
            NULL, HFILL }},
426
427
16
        { &hf_epmd_protocol,
428
16
          { "Protocol", "epmd.protocol",
429
16
            FT_UINT8, BASE_DEC, VALS(protocol_vals), 0x0,
430
16
            NULL, HFILL }},
431
432
16
        { &hf_epmd_creation,
433
16
          { "Creation", "epmd.creation",
434
16
            FT_UINT16, BASE_DEC, NULL, 0x0,
435
16
            NULL, HFILL }},
436
437
16
        { &hf_epmd_creation2,
438
16
          { "Creation", "epmd.creation2",
439
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
440
16
            "Creation (4 bytes)", HFILL }},
441
442
16
        { &hf_epmd_dist_high,
443
16
          { "Highest Version", "epmd.dist_high",
444
16
            FT_UINT16, BASE_DEC, VALS(epmd_version_vals), 0x0,
445
16
            NULL, HFILL }},
446
447
16
        { &hf_epmd_dist_low,
448
16
          { "Lowest Version", "epmd.dist_low",
449
16
            FT_UINT16, BASE_DEC, VALS(epmd_version_vals), 0x0,
450
16
            NULL, HFILL }},
451
452
16
        { &hf_epmd_name_len,
453
16
          { "Name Length", "epmd.name_len",
454
16
            FT_UINT16, BASE_DEC, NULL, 0x0,
455
16
            NULL, HFILL }},
456
457
16
        { &hf_epmd_name,
458
16
          { "Node Name", "epmd.name",
459
16
            FT_STRING, BASE_NONE, NULL, 0x0,
460
16
            NULL, HFILL }},
461
462
16
        { &hf_epmd_node_container,
463
16
            { "Node", "epmd.node",
464
16
                FT_NONE, BASE_NONE, NULL, 0x0,
465
16
                "Single EPMD node entry", HFILL }},
466
467
16
        { &hf_epmd_node_name,
468
16
            { "Name", "epmd.node_name",
469
16
                FT_STRING, BASE_NONE, NULL, 0x0,
470
16
                "Name of the Erlang node", HFILL }},
471
472
16
        { &hf_epmd_node_port,
473
16
            { "Port", "epmd.node_port",
474
16
                FT_UINT16, BASE_DEC, NULL, 0x0,
475
16
                "Port where the node is listening", HFILL }},
476
477
16
        { &hf_epmd_elen,
478
16
          { "Elen", "epmd.elen",
479
16
            FT_UINT16, BASE_DEC, NULL, 0x0,
480
16
            "Extra Length", HFILL }},
481
482
16
        { &hf_epmd_edata,
483
16
          { "Edata", "epmd.edata",
484
16
            FT_BYTES, BASE_NONE, NULL, 0x0,
485
16
            "Extra Data", HFILL }},
486
16
    };
487
488
16
    static ei_register_info ei[] = {
489
16
        { &ei_epmd_malformed_names_line,
490
16
        { "epmd.malformed_names_line", PI_MALFORMED, PI_ERROR,
491
16
            "Malformed line in EPMD names response", EXPFILL }},
492
16
    };
493
494
16
    static int *ett[] = {
495
16
        &ett_epmd,
496
16
        &ett_epmd_node,
497
16
    };
498
499
16
    proto_epmd = proto_register_protocol("Erlang Port Mapper Daemon", "EPMD", "epmd");
500
16
    proto_register_field_array(proto_epmd, hf, array_length(hf));
501
16
    proto_register_subtree_array(ett, array_length(ett));
502
16
    epmd_handle = register_dissector("epmd", dissect_epmd, proto_epmd);
503
504
16
    expert_epmd = expert_register_protocol(proto_epmd);
505
16
    expert_register_field_array(expert_epmd, ei, array_length(ei));
506
16
}
507
508
void
509
16
proto_reg_handoff_epmd(void) {
510
16
    edp_handle = find_dissector("erldp");
511
512
16
    dissector_add_uint_with_preference("tcp.port", EPMD_PORT, epmd_handle);
513
16
}
514
515
/*
516
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
517
 *
518
 * Local variables:
519
 * c-basic-offset: 4
520
 * tab-width: 8
521
 * indent-tabs-mode: nil
522
 * End:
523
 *
524
 * vi: set shiftwidth=4 tabstop=8 expandtab:
525
 * :indentSize=4:tabSize=8:noTabs=true:
526
 */