Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-realtek.c
blob0af98f28c9a4f11a6115227d22c021535b457584
1 /* packet-realtek.c
2 * Routines for Realtek layer 2 protocols dissection
4 * Based on code from a 2004 submission
5 * Copyright 2004, Horst Kronstorfer <hkronsto@frequentis.com>
6 * but significantly modernized.
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "config.h"
17 #include <string.h>
18 #include <epan/packet.h>
19 #include <etypes.h>
21 void proto_register_realtek(void);
22 void proto_reg_handoff_realtek(void);
24 #define RTL_PROTOCOL_RRCP 0x01 /* RRCP */
25 #define RTL_PROTOCOL_REP 0x02 /* REP */
26 #define RTL_PROTOCOL_RLDP 0x03 /* RLDP */
27 #define RTL_PROTOCOL_RLDP2 0x23 /* also RLDP */
28 #define RTL_PROTOCOL_XXX_DSA 0x04 /* DSA protocol for some chip(s) */
31 * Values for the upper 4 bits of the protocol field, for
32 * protocols where the lower 4 bits contain protocol data.
34 * See section 8.10 "CPU Tag Function" of
36 * http://realtek.info/pdf/rtl8306sd%28m%29_datasheet_1.1.pdf
38 * for the RTL8306 DSA protocol tag format.
40 #define RTL_PROTOCOL_8306_DSA 0x9 /* RTL8306 DSA protocol */
41 #define RTL_PROTOCOL_8366RB_DSA 0xA /* RTL8366RB DSA protocol */
43 enum {
44 RRCP_OPCODE_HELLO = 0,
45 RRCP_OPCODE_GET = 1,
46 RRCP_OPCODE_SET = 2
49 /* HELLO, HELLO_REPLY, GET, GET_REPLY, SET */
50 #define RRCP_OPCODE_FIELD_LENGTH 1
51 #define RRCP_REPLY_FIELD_LENGTH RRCP_OPCODE_FIELD_LENGTH
52 #define RRCP_REPLY_MASK 0x80
53 #define RRCP_REPLY_BIT_POS 7
54 #define RRCP_OPCODE_MASK 0x7f
55 #define RRCP_AUTHKEY_FIELD_LENGTH 2
56 /* GET, GET_REPLY, SET */
57 #define RRCP_REGADDR_FIELD_LENGTH 2
58 /* GET_REPLY, SET */
59 #define RRCP_REGDATA_FIELD_LENGTH 2
60 /* HELLO_REPLY */
61 #define RRCP_DLPORT_FIELD_LENGTH 1
62 #define RRCP_ULPORT_FIELD_LENGTH 1
63 #define RRCP_ULMAC_FIELD_LENGTH 6
64 #define RRCP_CHIPID_FIELD_LENGTH 2
65 #define RRCP_VENDID_FIELD_LENGTH 4
67 #define RRCP_HELLO_PACKET_LENGTH 4
68 #define RRCP_HELLO_REPLY_PACKET_LENGTH 18
69 #define RRCP_GET_SET_PACKET_LENGTH 8
71 static const value_string rrcp_opcode_names[] = {
72 { RRCP_OPCODE_HELLO, "Hello" },
73 { RRCP_OPCODE_GET, "Get" },
74 { RRCP_OPCODE_SET, "Set" },
75 {0, NULL}
78 static dissector_handle_t realtek_handle;
80 static int proto_realtek;
82 static int hf_realtek_packet;
84 static int proto_rrcp;
86 static int hf_rrcp_protocol;
87 static int hf_rrcp_reply;
88 static int hf_rrcp_opcode;
89 static int hf_rrcp_authkey;
90 static int hf_rrcp_regaddr;
91 static int hf_rrcp_regdata;
92 static int hf_rrcp_hello_reply_dl_port;
93 static int hf_rrcp_hello_reply_ul_port;
94 static int hf_rrcp_hello_reply_ul_mac;
95 static int hf_rrcp_hello_reply_chip_id;
96 static int hf_rrcp_hello_reply_vendor_id;
98 static int proto_rep;
99 static int hf_rep_protocol;
101 static int proto_rldp;
102 static int hf_rldp_protocol;
104 static int ett_realtek;
105 static int ett_rrcp;
106 static int ett_rep;
107 static int ett_rldp;
109 static heur_dissector_list_t realtek_heur_subdissector_list;
111 static const uint8_t ether_mac_bcast[] = {
112 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
115 /* Code to actually dissect the Realtek protocols */
116 static int
117 dissect_realtek(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
119 proto_item *ti;
120 proto_tree *realtek_tree;
121 heur_dtbl_entry_t *hdtbl_entry;
123 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Realtek");
124 col_clear(pinfo->cinfo, COL_INFO);
126 ti = proto_tree_add_item(tree, proto_realtek, tvb, 0, -1, ENC_NA);
127 realtek_tree = proto_item_add_subtree(ti, ett_realtek);
129 if (!dissector_try_heuristic(realtek_heur_subdissector_list, tvb, pinfo,
130 tree, &hdtbl_entry, NULL)) {
131 proto_tree_add_item(realtek_tree, hf_realtek_packet, tvb, 0, -1, ENC_NA);
133 return tvb_captured_length(tvb);
137 * See section 8.20 "Realtek Remote Control Protocol" of
139 * http://realtek.info/pdf/rtl8324.pdf
141 * and section 7.22 "Realtek Remote Control Protocol" of
143 * http://realtek.info/pdf/rtl8326.pdf
145 * and this page on the OpenRRCP Wiki:
147 * http://openrrcp.org.ru/wiki/rrcp_protocol
149 * for information on RRCP.
151 static bool
152 dissect_rrcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
154 proto_item *ti;
155 proto_tree *rrcp_tree;
156 uint8_t proto;
157 int offset = 0;
158 bool reply;
159 uint32_t opcode;
161 if (!tvb_bytes_exist(tvb, 0, 1))
162 return false;
163 proto = tvb_get_uint8(tvb, 0);
164 if (proto != RTL_PROTOCOL_RRCP)
165 return false;
167 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RRCP");
168 col_clear(pinfo->cinfo, COL_INFO);
170 ti = proto_tree_add_item(tree, proto_rrcp, tvb, 0, -1, ENC_NA);
171 rrcp_tree = proto_item_add_subtree(ti, ett_rrcp);
173 proto_tree_add_uint(rrcp_tree, hf_rrcp_protocol, tvb, offset, 1,
174 proto);
175 offset += 1;
176 proto_tree_add_item_ret_boolean(rrcp_tree, hf_rrcp_reply, tvb,
177 offset, RRCP_REPLY_FIELD_LENGTH,
178 ENC_NA, &reply);
179 proto_tree_add_item_ret_uint(rrcp_tree, hf_rrcp_opcode, tvb,
180 offset, RRCP_OPCODE_FIELD_LENGTH,
181 ENC_NA, &opcode);
182 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
183 val_to_str(opcode, rrcp_opcode_names, "Unknown (%u)"),
184 (reply) ? "Reply" : "Request");
185 offset += RRCP_OPCODE_FIELD_LENGTH;
187 proto_tree_add_item(rrcp_tree, hf_rrcp_authkey, tvb, offset,
188 RRCP_AUTHKEY_FIELD_LENGTH, ENC_BIG_ENDIAN);
189 offset += RRCP_AUTHKEY_FIELD_LENGTH;
191 if ((RRCP_OPCODE_GET == opcode) || (RRCP_OPCODE_SET == opcode)) {
192 proto_tree_add_item(rrcp_tree, hf_rrcp_regaddr, tvb, offset,
193 RRCP_REGADDR_FIELD_LENGTH, ENC_BIG_ENDIAN);
194 offset += RRCP_REGADDR_FIELD_LENGTH;
195 proto_tree_add_item(rrcp_tree, hf_rrcp_regdata, tvb, offset,
196 RRCP_REGDATA_FIELD_LENGTH, ENC_BIG_ENDIAN);
197 offset += RRCP_REGDATA_FIELD_LENGTH;
199 else if (RRCP_OPCODE_HELLO == opcode) {
200 if (reply) {
201 proto_tree_add_item(rrcp_tree, hf_rrcp_hello_reply_dl_port, tvb,
202 offset, RRCP_DLPORT_FIELD_LENGTH, ENC_NA);
203 offset += RRCP_DLPORT_FIELD_LENGTH;
204 proto_tree_add_item(rrcp_tree, hf_rrcp_hello_reply_ul_port, tvb,
205 offset, RRCP_ULPORT_FIELD_LENGTH, ENC_NA);
206 offset += RRCP_ULPORT_FIELD_LENGTH;
207 proto_tree_add_item(rrcp_tree, hf_rrcp_hello_reply_ul_mac, tvb,
208 offset, RRCP_ULMAC_FIELD_LENGTH, ENC_NA);
209 offset += RRCP_ULMAC_FIELD_LENGTH;
210 proto_tree_add_item(rrcp_tree, hf_rrcp_hello_reply_chip_id, tvb,
211 offset, RRCP_CHIPID_FIELD_LENGTH, ENC_BIG_ENDIAN);
212 offset += RRCP_CHIPID_FIELD_LENGTH;
213 proto_tree_add_item(rrcp_tree, hf_rrcp_hello_reply_vendor_id, tvb,
214 offset, RRCP_VENDID_FIELD_LENGTH, ENC_BIG_ENDIAN);
215 offset += RRCP_VENDID_FIELD_LENGTH;
218 proto_item_set_end(ti, tvb, offset);
219 /* Let 'packet-eth' provide trailer/pad-bytes info */
220 tvb_set_reported_length(tvb, offset);
221 return true;
225 * See section 8.22 "Realtek Echo Protocol" of
227 * http://realtek.info/pdf/rtl8324.pdf
229 * and section 7.24 "Realtek Echo Protocol" of
231 * http://realtek.info/pdf/rtl8326.pdf
233 * for information on REP.
235 static bool
236 dissect_rep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
238 proto_item *ti;
239 proto_tree *rep_tree;
240 uint8_t proto;
241 int offset = 0;
242 bool bcast;
244 if (!tvb_bytes_exist(tvb, 0, 1))
245 return false;
246 proto = tvb_get_uint8(tvb, 0);
247 if (proto != RTL_PROTOCOL_REP)
248 return false;
250 ti = proto_tree_add_item(tree, proto_rep, tvb, 0, -1, ENC_NA);
251 rep_tree = proto_item_add_subtree(ti, ett_rep);
253 bcast = (pinfo->dst.type == AT_ETHER &&
254 memcmp(pinfo->dst.data, ether_mac_bcast, 6) == 0);
256 col_set_str(pinfo->cinfo, COL_PROTOCOL, "REP");
257 col_add_fstr(pinfo->cinfo, COL_INFO,
258 "Echo %s", (bcast) ? "Request" : "Reply");
260 proto_tree_add_uint(rep_tree, hf_rep_protocol, tvb, offset, 1,
261 proto);
262 offset += 1;
264 proto_item_set_end(ti, tvb, offset);
265 /* Let 'packet-eth' provide trailer/pad-bytes info */
266 tvb_set_reported_length(tvb, offset);
267 return true;
271 * See section 8.21 "Network Loop Connection Fault Detection" of
273 * http://realtek.info/pdf/rtl8324.pdf
275 * and section 7.23 "Network Loop Connection Fault Detection" of
277 * http://realtek.info/pdf/rtl8326.pdf
279 * for information on RLDP.
281 * See also section 7.3.8 "Loop Detection" of
283 * http://www.ibselectronics.com/ibsstore/datasheet/RTL8306E-CG.pdf
285 * (revision 1.1 of the RTL8306E-CG datasheet), which describes a loop
286 * detection protocol for which the payload has a 16-bit (presumably
287 * big-endian) field containing the value 0x0300, followed by what is
288 * presumably a 16-bit big-endian field the upper 12 bits of which are 0
289 * and the lower 4 bits of which are a TTL value, followed by zeroes to
290 * pad the packet out to the minimum Ethernet packet size.
292 * See also section 7.3.13 "Loop Detection" of
294 * http://realtek.info/pdf/rtl8305sb.pdf
296 * (revision 1.3 of the RTL8305SB datasheet), which describes a similar
297 * loop detection protocol that lacks the TTL field - all the bytes
298 * after 0x0300 are zero.
300 * See also section 7.3.7 "Loop Detection" of
302 * https://datasheet.lcsc.com/lcsc/1810221720_Realtek-Semicon-RTL8305NB-CG_C52146.pdf
304 * (revision 1.0 of the RTL8305NB-CT datasheet), which describes a loop
305 * detection protocol similar to the one from the RTL8306E-CG datasheet,
306 * except that the first value is 0x2300, not 0x0300.
308 * And, on top of all that, I've seen packets where the first octet of
309 * the packet is 0x23, and that's followed by 6 unknown octets (a MAC
310 * address of some sort? It differs from packet to packet in a capture),
311 * followed by the MAC address that appears in the source address in the
312 * Ethernet header (possibly the originator, in case the packet is forwarded,
313 * in which case the forwarded packets won't have the source address from
314 * the Ethernet header there), followed by unknown stuff (0x0d followed by
315 * zeroes for all such packets in one capture, 0x01 followed by zeroes for
316 * all such packets in another capture, 0x07 followed by 0x20's for all
317 * such packets in yet another capture). The OpenRRCP issue at
318 * https://github.com/illarionov/OpenRRCP/issues/3 shows a capture
319 * similar to the last of those, but with 0x02 instead of 0x07. Or is that
320 * just crap in the buffer in which the chip constructed the packet, left
321 * over from something else?
323 static bool
324 dissect_rldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
326 proto_item *ti;
327 proto_tree *rldp_tree;
328 uint8_t proto;
329 int offset = 0;
331 if (!tvb_bytes_exist(tvb, 0, 1))
332 return false;
333 proto = tvb_get_uint8(tvb, 0);
334 if (proto != RTL_PROTOCOL_RLDP && proto != RTL_PROTOCOL_RLDP2)
335 return false;
337 ti = proto_tree_add_item(tree, proto_rldp, tvb, 0, -1, ENC_NA);
338 rldp_tree = proto_item_add_subtree(ti, ett_rep);
340 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLDP");
341 col_set_str(pinfo->cinfo, COL_INFO, "Network Loop Detection");
343 proto_tree_add_uint(rldp_tree, hf_rldp_protocol, tvb, offset, 1,
344 proto);
345 offset += 1;
347 proto_item_set_end(ti, tvb, offset);
348 /* Let 'packet-eth' provide trailer/pad-bytes info */
349 tvb_set_reported_length(tvb, offset);
350 return true;
353 /* Register the protocol with Ethereal */
354 void
355 proto_register_realtek(void)
357 static hf_register_info hf_realtek[] = {
358 { &hf_realtek_packet, {
359 "Unknown packet", "realtek.packet", FT_BYTES, BASE_NONE,
360 NULL, 0x0, NULL, HFILL }},
363 static hf_register_info hf_rrcp[] = {
364 { &hf_rrcp_protocol, {
365 "Protocol", "rrcp.protocol", FT_UINT8, BASE_HEX,
366 NULL, 0x0, NULL, HFILL }},
367 { &hf_rrcp_reply, {
368 "Reply", "rrcp.reply", FT_BOOLEAN, 8,
369 NULL, RRCP_REPLY_MASK, "RRCP reply flag", HFILL}},
370 { &hf_rrcp_opcode, {
371 "Opcode", "rrcp.opcode", FT_UINT8, BASE_HEX,
372 VALS(rrcp_opcode_names), RRCP_OPCODE_MASK, "RRCP operation code",
373 HFILL }},
374 { &hf_rrcp_authkey, {
375 "Authentication key", "rrcp.authkey", FT_UINT16, BASE_HEX,
376 NULL, 0, "RRCP authentication key", HFILL }},
377 { &hf_rrcp_regaddr, {
378 "Register address", "rrcp.regaddr", FT_UINT16, BASE_HEX,
379 NULL, 0, "RRCP register address", HFILL }},
380 { &hf_rrcp_regdata, {
381 "Register data", "rrcp.regdata", FT_UINT16, BASE_HEX,
382 NULL, 0, "RRCP register data", HFILL }},
383 { &hf_rrcp_hello_reply_dl_port, {
384 "Downlink port number", "rrcp.hello_reply.downlink_port",
385 FT_UINT8, BASE_DEC, NULL, 0, "RRCP hello reply downlink port", HFILL }},
386 { &hf_rrcp_hello_reply_ul_port, {
387 "Uplink port number", "rrcp.hello_reply.uplink_port", FT_UINT8,
388 BASE_DEC, NULL, 0, "RRCP hello reply uplink port", HFILL }},
389 { &hf_rrcp_hello_reply_ul_mac, {
390 "Uplink MAC address", "rrcp.hello_reply.uplink_mac", FT_ETHER,
391 BASE_NONE, NULL, 0, "RRCP hello reply uplink MAC address", HFILL }},
392 { &hf_rrcp_hello_reply_chip_id, {
393 "Chip ID", "rrcp.hello_reply.chip_id", FT_UINT16,
394 BASE_HEX, NULL, 0, "RRCP hello reply chip ID", HFILL }},
395 { &hf_rrcp_hello_reply_vendor_id, {
396 "Vendor ID", "rrcp.hello_reply.vendor_id", FT_UINT32, BASE_HEX,
397 NULL, 0, "RRCP hello reply vendor ID", HFILL }}
400 static hf_register_info hf_rep[] = {
401 { &hf_rep_protocol, {
402 "Protocol", "rep.protocol", FT_UINT8, BASE_HEX,
403 NULL, 0x0, NULL, HFILL }},
406 static hf_register_info hf_rldp[] = {
407 { &hf_rldp_protocol, {
408 "Protocol", "rldp.protocol", FT_UINT8, BASE_HEX,
409 NULL, 0x0, NULL, HFILL }},
412 static int *ett[] = {
413 &ett_realtek,
414 &ett_rrcp,
415 &ett_rep,
416 &ett_rldp
419 proto_realtek = proto_register_protocol("Realtek Layer 2 Protocols",
420 "Realtek", "realtek");
421 realtek_handle = register_dissector("realtek", dissect_realtek, proto_realtek);
422 proto_register_field_array(proto_realtek, hf_realtek, array_length(hf_realtek));
423 realtek_heur_subdissector_list = register_heur_dissector_list_with_description("realtek",
424 "Realtek Layer 2 payload",
425 proto_realtek);
427 proto_rrcp = proto_register_protocol("Realtek Remote Control Protocol",
428 "RRCP", "rrcp");
429 proto_register_field_array(proto_rrcp, hf_rrcp, array_length(hf_rrcp));
431 proto_rep = proto_register_protocol("Realtek Echo Protocol",
432 "REP", "rep");
433 proto_register_field_array(proto_rrcp, hf_rep, array_length(hf_rep));
435 proto_rldp = proto_register_protocol("Realtek Loop Detection Protocol",
436 "RLDP", "rldp");
437 proto_register_field_array(proto_rrcp, hf_rldp, array_length(hf_rldp));
439 proto_register_subtree_array(ett, array_length(ett));
442 /* Sub-dissector registration */
443 void
444 proto_reg_handoff_realtek(void)
446 dissector_add_uint("ethertype", ETHERTYPE_REALTEK, realtek_handle);
448 heur_dissector_add("realtek", dissect_rrcp, "Realtek Remote Control Protocol",
449 "rrcp", proto_rrcp, HEURISTIC_ENABLE);
451 heur_dissector_add("realtek", dissect_rep, "Realtek Echo Protocol",
452 "rep", proto_rep, HEURISTIC_ENABLE);
454 heur_dissector_add("realtek", dissect_rldp, "Realtek Loop Detection Protocol",
455 "rldp", proto_rldp, HEURISTIC_ENABLE);