2 * Routines for MAC-Telnet dissection
3 * Copyright 2010, Haakon Nessjoen <haakon.nessjoen@gmail.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * Thanks to "omniflux" for dissecting the protocol by hand before me.
14 * http://www.omniflux.com/devel/mikrotik/Mikrotik_MAC_Telnet_Procotol.txt
19 #include <epan/packet.h>
20 #include <epan/to_str.h>
22 void proto_register_mactelnet(void);
23 void proto_reg_handoff_mactelnet(void);
25 #define PROTO_TAG_MACTELNET "MAC-Telnet"
27 /* Initialize the protocol and registered fields */
28 static int proto_mactelnet
;
29 static int hf_mactelnet_control_packet
;
30 static int hf_mactelnet_type
;
31 static int hf_mactelnet_protocolver
;
32 static int hf_mactelnet_source_mac
;
33 static int hf_mactelnet_destination_mac
;
34 static int hf_mactelnet_session_id
;
35 static int hf_mactelnet_client_type
;
36 static int hf_mactelnet_databytes
;
37 static int hf_mactelnet_datatype
;
38 static int hf_mactelnet_control
;
39 static int hf_mactelnet_control_length
;
40 static int hf_mactelnet_control_encryption_key
;
41 static int hf_mactelnet_control_password
;
42 static int hf_mactelnet_control_username
;
43 static int hf_mactelnet_control_terminal
;
44 static int hf_mactelnet_control_width
;
45 static int hf_mactelnet_control_height
;
47 #define MACTELNET_UDP_PORT 20561 /* Not IANA registered */
49 /* Control packet definition */
50 static const uint32_t control_packet
= 0x563412FF;
52 /* Initialize the subtree pointers */
53 static int ett_mactelnet
;
54 static int ett_mactelnet_control
;
57 static const value_string packettypenames
[] = {
58 { 0, "Start session" },
61 { 4, "Ping request" },
62 { 5, "Ping response" },
63 { 255, "End session" },
67 /* Known client types */
68 static const value_string clienttypenames
[] = {
69 { 0x0015, "MAC Telnet" },
74 /* Known control-packet types */
75 static const value_string controlpackettypenames
[] = {
76 { 0, "Begin authentication" },
77 { 1, "Encryption key" },
80 { 4, "Terminal type" },
81 { 5, "Terminal width" },
82 { 6, "Terminal height" },
83 { 9, "End authentication" },
89 dissect_mactelnet(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
91 proto_item
*mactelnet_item
;
92 proto_tree
*mactelnet_tree
;
93 proto_item
*mactelnet_control_item
;
94 proto_tree
*mactelnet_control_tree
;
100 /* Check that there's enough data */
101 if (tvb_captured_length(tvb
) < 18)
104 /* Get the type byte */
105 type
= tvb_get_uint8(tvb
, 1);
107 if ((type
== 4) || (type
== 5)) { /* Ping */
111 while (clienttypenames
[i
].strptr
!= NULL
) {
112 if (tvb_get_ntohs(tvb
, 14) == clienttypenames
[i
].value
) {
116 if (tvb_get_ntohs(tvb
, 16) == clienttypenames
[i
].value
) {
124 /* Not a mactelnet packet */
125 if ((foundping
< 0) && (foundclient
< 0) && (foundserver
< 0)) {
129 /* Make entries in Protocol column and Info column on summary display */
130 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PROTO_TAG_MACTELNET
);
132 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s > %s Direction: %s Type: %s",
133 tvb_ether_to_str(pinfo
->pool
, tvb
, 2),
134 tvb_ether_to_str(pinfo
->pool
, tvb
, 8),
135 ((foundclient
>= 0) || (type
== 4) ? "Client->Server" : "Server->Client" ),
136 val_to_str(type
, packettypenames
, "Unknown Type:0x%02x")
142 /* create display subtree for the protocol */
143 mactelnet_item
= proto_tree_add_item(tree
, proto_mactelnet
, tvb
, 0, -1, ENC_NA
);
144 mactelnet_tree
= proto_item_add_subtree(mactelnet_item
, ett_mactelnet
);
147 proto_tree_add_item(mactelnet_tree
, hf_mactelnet_protocolver
, tvb
, offset
, 1, ENC_NA
);
151 proto_tree_add_item(mactelnet_tree
, hf_mactelnet_type
, tvb
, offset
, 1, ENC_NA
);
155 proto_tree_add_item(mactelnet_tree
, hf_mactelnet_source_mac
, tvb
, offset
, 6, ENC_NA
);
159 proto_tree_add_item(mactelnet_tree
, hf_mactelnet_destination_mac
, tvb
, offset
, 6, ENC_NA
);
162 if (foundserver
>= 0) {
163 /* Server to client */
166 proto_tree_add_item(mactelnet_tree
, hf_mactelnet_session_id
, tvb
, offset
+2, 2, ENC_BIG_ENDIAN
);
170 proto_tree_add_item(mactelnet_tree
, hf_mactelnet_client_type
, tvb
, offset
-2, 2, ENC_BIG_ENDIAN
);
172 } else if (foundclient
>= 0) {
173 /* Client to server */
176 proto_tree_add_item(mactelnet_tree
, hf_mactelnet_session_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
180 proto_tree_add_item(mactelnet_tree
, hf_mactelnet_client_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
182 } else if (foundping
>= 0) {
183 /* Skip empty data */
189 proto_tree_add_item(mactelnet_tree
, hf_mactelnet_databytes
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
193 /* Data packets only */
195 while(tvb_reported_length_remaining(tvb
, offset
) > 0) {
196 if ((tvb_reported_length_remaining(tvb
, offset
) > 4) && (tvb_get_ntohl(tvb
, offset
) == control_packet
)) {
200 /* Add subtree for control packet */
201 mactelnet_control_item
= proto_tree_add_item(mactelnet_tree
, hf_mactelnet_control
, tvb
, offset
, -1, ENC_NA
);
202 mactelnet_control_tree
= proto_item_add_subtree(mactelnet_control_item
, ett_mactelnet
);
203 /* Control packet magic number (4) */
204 proto_tree_add_item(mactelnet_control_tree
, hf_mactelnet_control_packet
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
207 /* Control packet type (1) */
208 datatype
= tvb_get_uint8(tvb
, offset
);
209 proto_tree_add_item(mactelnet_control_tree
, hf_mactelnet_datatype
, tvb
, offset
, 1, ENC_NA
);
212 /* Control packet length (4) */
213 datalength
= tvb_get_ntohl(tvb
, offset
);
214 proto_tree_add_item(mactelnet_control_tree
, hf_mactelnet_control_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
218 case 1: /* Encryption Key */
219 proto_tree_add_item(mactelnet_control_tree
, hf_mactelnet_control_encryption_key
, tvb
, offset
, datalength
, ENC_NA
);
222 case 2: /* Password */
223 proto_tree_add_item(mactelnet_control_tree
, hf_mactelnet_control_password
, tvb
, offset
, datalength
, ENC_NA
);
226 case 3: /* Username */
227 proto_tree_add_item(mactelnet_control_tree
, hf_mactelnet_control_username
, tvb
, offset
, datalength
, ENC_ASCII
);
230 case 4: /* Terminal type */
231 proto_tree_add_item(mactelnet_control_tree
, hf_mactelnet_control_terminal
, tvb
, offset
, datalength
, ENC_ASCII
);
234 case 5: /* Terminal width */
235 proto_tree_add_item(mactelnet_control_tree
, hf_mactelnet_control_width
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
238 case 6: /* Terminal height */
239 proto_tree_add_item(mactelnet_control_tree
, hf_mactelnet_control_height
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
242 case 9: /* End authentication (no data) */
245 proto_item_set_len (mactelnet_control_item
, datalength
+ 9);
246 offset
+= datalength
;
248 /* Data packet, let wireshark handle it */
249 tvbuff_t
*next_client
= tvb_new_subset_remaining(tvb
, offset
);
250 return call_data_dissector(next_client
, pinfo
, mactelnet_tree
);
253 } else if ((type
== 4) || (type
== 5)) {
254 /* Data packet, let wireshark handle it */
255 tvbuff_t
*next_client
= tvb_new_subset_remaining(tvb
, offset
);
256 return call_data_dissector(next_client
, pinfo
, mactelnet_tree
);
261 return tvb_reported_length(tvb
);
266 proto_register_mactelnet(void)
268 static hf_register_info hf
[] = {
269 { &hf_mactelnet_control_packet
,
270 { "Control Packet Magic Number", "mactelnet.control_packet",
271 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
274 { &hf_mactelnet_type
,
275 { "Type", "mactelnet.type",
276 FT_UINT8
, BASE_DEC
, VALS(packettypenames
), 0x0,
277 "Packet Type", HFILL
}
279 { &hf_mactelnet_protocolver
,
280 { "Protocol Version", "mactelnet.protocol_version",
281 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
284 { &hf_mactelnet_source_mac
,
285 { "Source MAC", "mactelnet.source_mac",
286 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
289 { &hf_mactelnet_destination_mac
,
290 { "Destination MAC", "mactelnet.destination_mac",
291 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
294 { &hf_mactelnet_session_id
,
295 { "Session ID", "mactelnet.session_id",
296 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
297 "Session ID for this connection", HFILL
}
299 { &hf_mactelnet_client_type
,
300 { "Client Type", "mactelnet.client_type",
301 FT_UINT16
, BASE_HEX
, VALS(clienttypenames
) , 0x0,
304 { &hf_mactelnet_databytes
,
305 { "Session Data Bytes", "mactelnet.session_bytes",
306 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
307 "Session data bytes received", HFILL
}
309 { &hf_mactelnet_datatype
,
310 { "Data Packet Type", "mactelnet.data_type",
311 FT_UINT8
, BASE_HEX
, VALS(controlpackettypenames
) , 0x0,
314 { &hf_mactelnet_control
,
315 { "Control Packet", "mactelnet.control",
316 FT_NONE
, BASE_NONE
, NULL
, 0x0,
319 { &hf_mactelnet_control_length
,
320 { "Control Data Length", "mactelnet.control_length",
321 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
322 "Control packet length", HFILL
}
324 { &hf_mactelnet_control_encryption_key
,
325 { "Encryption Key", "mactelnet.control_encryptionkey",
326 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
327 "Login encryption key", HFILL
}
329 { &hf_mactelnet_control_password
,
330 { "Password MD5", "mactelnet.control_password",
331 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
332 "Null padded MD5 password", HFILL
}
334 { &hf_mactelnet_control_username
,
335 { "Username", "mactelnet.control_username",
336 FT_STRING
, BASE_NONE
, NULL
, 0x0,
339 { &hf_mactelnet_control_terminal
,
340 { "Terminal Type", "mactelnet.control_terminaltype",
341 FT_STRING
, BASE_NONE
, NULL
, 0x0,
344 { &hf_mactelnet_control_width
,
345 { "Terminal Width", "mactelnet.control_width",
346 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
349 { &hf_mactelnet_control_height
,
350 { "Terminal Height", "mactelnet.control_height",
351 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
356 /* Setup protocol subtree array */
357 static int *ett
[] = {
359 &ett_mactelnet_control
,
362 /* Register the protocol name and description */
363 proto_mactelnet
= proto_register_protocol ("MikroTik MAC-Telnet Protocol", PROTO_TAG_MACTELNET
, "mactelnet");
364 register_dissector("mactelnet", dissect_mactelnet
, proto_mactelnet
);
366 /* Required function calls to register the header fields and subtrees used */
367 proto_register_field_array (proto_mactelnet
, hf
, array_length (hf
));
368 proto_register_subtree_array (ett
, array_length (ett
));
372 proto_reg_handoff_mactelnet(void)
374 dissector_add_uint_with_preference("udp.port", MACTELNET_UDP_PORT
, find_dissector("mactelnet"));
378 * Editor modelines - https://www.wireshark.org/tools/modelines.html
383 * indent-tabs-mode: nil
386 * vi: set shiftwidth=4 tabstop=8 expandtab:
387 * :indentSize=4:tabSize=8:noTabs=true: