/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 | | */ |