Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-mactelnet.c
blobca5c8c822c2285f6c67a8238d599a3fbbb36bcc6
1 /* packet-mactelnet.c
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
17 #include "config.h"
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;
56 /* Packet types */
57 static const value_string packettypenames[] = {
58 { 0, "Start session" },
59 { 1, "Data" },
60 { 2, "Acknowledge" },
61 { 4, "Ping request" },
62 { 5, "Ping response" },
63 { 255, "End session" },
64 { 0, NULL }
67 /* Known client types */
68 static const value_string clienttypenames[] = {
69 { 0x0015, "MAC Telnet" },
70 { 0x0f90, "Winbox" },
71 { 0, NULL }
74 /* Known control-packet types */
75 static const value_string controlpackettypenames[] = {
76 { 0, "Begin authentication" },
77 { 1, "Encryption key" },
78 { 2, "Password" },
79 { 3, "Username" },
80 { 4, "Terminal type" },
81 { 5, "Terminal width" },
82 { 6, "Terminal height" },
83 { 9, "End authentication" },
84 { 0, NULL }
88 static int
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;
95 int foundping = -1;
96 int foundclient = -1;
97 int foundserver = -1;
98 uint16_t type;
100 /* Check that there's enough data */
101 if (tvb_captured_length(tvb) < 18)
102 return 0;
104 /* Get the type byte */
105 type = tvb_get_uint8(tvb, 1);
107 if ((type == 4) || (type == 5)) { /* Ping */
108 foundping = 1;
109 } else {
110 int i = 0;
111 while (clienttypenames[i].strptr != NULL) {
112 if (tvb_get_ntohs(tvb, 14) == clienttypenames[i].value) {
113 foundserver = i;
114 break;
116 if (tvb_get_ntohs(tvb, 16) == clienttypenames[i].value) {
117 foundclient = i;
118 break;
120 i++;
124 /* Not a mactelnet packet */
125 if ((foundping < 0) && (foundclient < 0) && (foundserver < 0)) {
126 return 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")
139 if (tree) {
140 uint32_t offset = 0;
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);
146 /* ver(1) */
147 proto_tree_add_item(mactelnet_tree, hf_mactelnet_protocolver, tvb, offset, 1, ENC_NA);
148 offset += 1;
150 /* ptype(1) */
151 proto_tree_add_item(mactelnet_tree, hf_mactelnet_type, tvb, offset, 1, ENC_NA);
152 offset += 1;
154 /* saddr(6) */
155 proto_tree_add_item(mactelnet_tree, hf_mactelnet_source_mac, tvb, offset, 6, ENC_NA);
156 offset += 6;
158 /* dstaddr(6) */
159 proto_tree_add_item(mactelnet_tree, hf_mactelnet_destination_mac, tvb, offset, 6, ENC_NA);
160 offset += 6;
162 if (foundserver >= 0) {
163 /* Server to client */
165 /* sessionid(2) */
166 proto_tree_add_item(mactelnet_tree, hf_mactelnet_session_id, tvb, offset+2, 2, ENC_BIG_ENDIAN);
167 offset += 2;
169 /* clienttype(2) */
170 proto_tree_add_item(mactelnet_tree, hf_mactelnet_client_type, tvb, offset-2, 2, ENC_BIG_ENDIAN);
171 offset += 2;
172 } else if (foundclient >= 0) {
173 /* Client to server */
175 /* sessionid(2) */
176 proto_tree_add_item(mactelnet_tree, hf_mactelnet_session_id, tvb, offset, 2, ENC_BIG_ENDIAN);
177 offset += 2;
179 /* clienttype(2) */
180 proto_tree_add_item(mactelnet_tree, hf_mactelnet_client_type, tvb, offset, 2, ENC_BIG_ENDIAN);
181 offset += 2;
182 } else if (foundping >= 0) {
183 /* Skip empty data */
184 offset += 4;
187 if (foundping < 0) {
188 /* counter(4) */
189 proto_tree_add_item(mactelnet_tree, hf_mactelnet_databytes, tvb, offset, 4, ENC_BIG_ENDIAN);
190 offset += 4;
193 /* Data packets only */
194 if (type == 1) {
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)) {
197 uint8_t datatype;
198 uint32_t datalength;
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);
205 offset += 4;
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);
210 offset += 1;
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);
215 offset += 4;
217 switch (datatype) {
218 case 1: /* Encryption Key */
219 proto_tree_add_item(mactelnet_control_tree, hf_mactelnet_control_encryption_key, tvb, offset, datalength, ENC_NA);
220 break;
222 case 2: /* Password */
223 proto_tree_add_item(mactelnet_control_tree, hf_mactelnet_control_password, tvb, offset, datalength, ENC_NA);
224 break;
226 case 3: /* Username */
227 proto_tree_add_item(mactelnet_control_tree, hf_mactelnet_control_username, tvb, offset, datalength, ENC_ASCII);
228 break;
230 case 4: /* Terminal type */
231 proto_tree_add_item(mactelnet_control_tree, hf_mactelnet_control_terminal, tvb, offset, datalength, ENC_ASCII);
232 break;
234 case 5: /* Terminal width */
235 proto_tree_add_item(mactelnet_control_tree, hf_mactelnet_control_width, tvb, offset, 2, ENC_LITTLE_ENDIAN);
236 break;
238 case 6: /* Terminal height */
239 proto_tree_add_item(mactelnet_control_tree, hf_mactelnet_control_height, tvb, offset, 2, ENC_LITTLE_ENDIAN);
240 break;
242 case 9: /* End authentication (no data) */
243 break;
245 proto_item_set_len (mactelnet_control_item, datalength + 9);
246 offset += datalength;
247 } else {
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);
265 void
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,
272 NULL, HFILL }
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,
282 NULL, HFILL }
284 { &hf_mactelnet_source_mac,
285 { "Source MAC", "mactelnet.source_mac",
286 FT_ETHER, BASE_NONE, NULL , 0x0,
287 NULL, HFILL }
289 { &hf_mactelnet_destination_mac,
290 { "Destination MAC", "mactelnet.destination_mac",
291 FT_ETHER, BASE_NONE, NULL , 0x0,
292 NULL, HFILL }
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,
302 NULL, HFILL }
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,
312 NULL, HFILL }
314 { &hf_mactelnet_control,
315 { "Control Packet", "mactelnet.control",
316 FT_NONE, BASE_NONE, NULL , 0x0,
317 NULL, HFILL }
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,
337 NULL, HFILL }
339 { &hf_mactelnet_control_terminal,
340 { "Terminal Type", "mactelnet.control_terminaltype",
341 FT_STRING, BASE_NONE, NULL , 0x0,
342 NULL, HFILL }
344 { &hf_mactelnet_control_width,
345 { "Terminal Width", "mactelnet.control_width",
346 FT_UINT16, BASE_DEC, NULL , 0x0,
347 NULL, HFILL }
349 { &hf_mactelnet_control_height,
350 { "Terminal Height", "mactelnet.control_height",
351 FT_UINT16, BASE_DEC, NULL , 0x0,
352 NULL, HFILL }
356 /* Setup protocol subtree array */
357 static int *ett[] = {
358 &ett_mactelnet,
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));
371 void
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
380 * Local variables:
381 * c-basic-offset: 4
382 * tab-width: 8
383 * indent-tabs-mode: nil
384 * End:
386 * vi: set shiftwidth=4 tabstop=8 expandtab:
387 * :indentSize=4:tabSize=8:noTabs=true: