1 /* 2 * Copyright (c) 2007 - Andrey "nording" Chernyak <andrew@nording.ru> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that: (1) source code distributions 6 * retain the above copyright notice and this paragraph in its entirety, (2) 7 * distributions including binary code include the above copyright notice and 8 * this paragraph in its entirety in the documentation or other materials 9 * provided with the distribution, and (3) all advertising materials mentioning 10 * features or use of this software display the following acknowledgement: 11 * ``This product includes software developed by the University of California, 12 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 13 * the University nor the names of its contributors may be used to endorse 14 * or promote products derived from this software without specific prior 15 * written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * Format and print Realtek Remote Control Protocol (RRCP), Realtek 21 * Loop Detection Protocol (RLDP), and Realtek Echo Protocol (REP) packets, 22 * as well as tag formats used by some Realtek switch chips to supply 23 * tag information to a host CPU for a switch. 24 */ 25 26 /* \summary: printer for various Realtek protocols */ 27 28 #ifdef HAVE_CONFIG_H 29 #include <config.h> 30 #endif 31 32 #include "netdissect-stdinc.h" 33 34 #include "netdissect.h" 35 #include "addrtoname.h" 36 #include "extract.h" 37 38 #define RTL_PROTOCOL_OFFSET 0 /* Protocol and possibly other data - 1 byte */ 39 40 #define RTL_PROTOCOL_RRCP 0x01 /* RRCP */ 41 #define RTL_PROTOCOL_REP 0x02 /* REP */ 42 #define RTL_PROTOCOL_RLDP 0x03 /* RLDP */ 43 #define RTL_PROTOCOL_RLDP2 0x23 /* also RLDP */ 44 #define RTL_PROTOCOL_XXX_DSA 0x04 /* DSA protocol for some chip(s) */ 45 46 /* 47 * Values for the upper 4 bits of the protocol field, for 48 * protocols where the lower 4 bits contain protocol data. 49 * 50 * See section 8.10 "CPU Tag Function" of 51 * 52 * http://realtek.info/pdf/rtl8306sd%28m%29_datasheet_1.1.pdf 53 * 54 * for the RTL8306 DSA protocol tag format. 55 */ 56 #define RTL_PROTOCOL_8306_DSA 0x90 /* RTL8306 DSA protocol */ 57 #define RTL_PROTOCOL_8366RB_DSA 0xA0 /* RTL8366RB DSA protocol */ 58 59 #define RRCP_OPCODE_ISREPLY_OFFSET 1 /* opcode and isreply flag - 1 byte */ 60 61 #define RRCP_OPCODE_MASK 0x7F /* 0x00 = hello, 0x01 = get, 0x02 = set */ 62 #define RRCP_ISREPLY 0x80 /* 0 = request to switch, 0x80 = reply from switch */ 63 64 #define RRCP_OPCODE_HELLO 0x00 65 #define RRCP_OPCODE_GET_CONFIGURATION 0x01 66 #define RRCP_OPCODE_SET_CONFIGURATION 0x02 67 68 #define RRCP_AUTHKEY_OFFSET 2 /* authorization key - 2 bytes, 0x2379 by default */ 69 70 /* most packets */ 71 #define RRCP_REG_ADDR_OFFSET 4 /* register address - 2 bytes */ 72 #define RRCP_REG_DATA_OFFSET 6 /* register data - 4 bytes */ 73 #define RRCP_COOKIE1_OFFSET 10 /* 4 bytes */ 74 #define RRCP_COOKIE2_OFFSET 14 /* 4 bytes */ 75 76 /* hello reply packets */ 77 #define RRCP_DOWNLINK_PORT_OFFSET 4 /* 1 byte */ 78 #define RRCP_UPLINK_PORT_OFFSET 5 /* 1 byte */ 79 #define RRCP_UPLINK_MAC_OFFSET 6 /* 6 byte MAC address */ 80 #define RRCP_CHIP_ID_OFFSET 12 /* 2 bytes */ 81 #define RRCP_VENDOR_ID_OFFSET 14 /* 4 bytes */ 82 83 static const struct tok opcode_values[] = { 84 { RRCP_OPCODE_HELLO, "hello" }, 85 { RRCP_OPCODE_GET_CONFIGURATION, "get" }, 86 { RRCP_OPCODE_SET_CONFIGURATION, "set" }, 87 { 0, NULL } 88 }; 89 90 /* 91 * Print RRCP packets. 92 * 93 * See, for example, section 8.20 "Realtek Remote Control Protocol" of 94 * 95 * http://realtek.info/pdf/rtl8324.pdf 96 * 97 * and section 7.22 "Realtek Remote Control Protocol" of 98 * 99 * http://realtek.info/pdf/rtl8326.pdf 100 * 101 * and this page on the OpenRRCP Wiki: 102 * 103 * http://openrrcp.org.ru/wiki/rrcp_protocol 104 * 105 * for information on RRCP. 106 */ 107 static void 108 rrcp_print(netdissect_options *ndo, 109 const u_char *cp) 110 { 111 uint8_t rrcp_opcode; 112 113 ndo->ndo_protocol = "rrcp"; 114 rrcp_opcode = GET_U_1((cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_OPCODE_MASK; 115 ND_PRINT("RRCP %s: %s", 116 ((GET_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY) ? "reply" : "query", 117 tok2str(opcode_values,"unknown opcode (0x%02x)",rrcp_opcode)); 118 if (rrcp_opcode==RRCP_OPCODE_GET_CONFIGURATION || 119 rrcp_opcode==RRCP_OPCODE_SET_CONFIGURATION){ 120 ND_PRINT(" addr=0x%04x, data=0x%08x", 121 GET_LE_U_2(cp + RRCP_REG_ADDR_OFFSET), 122 GET_LE_U_4(cp + RRCP_REG_DATA_OFFSET)); 123 } 124 ND_PRINT(", auth=0x%04x", 125 GET_BE_U_2(cp + RRCP_AUTHKEY_OFFSET)); 126 if (rrcp_opcode==RRCP_OPCODE_HELLO && 127 ((GET_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY)){ 128 ND_PRINT(" downlink_port=%u, uplink_port=%u, uplink_mac=%s, vendor_id=%08x ,chip_id=%04x ", 129 GET_U_1(cp + RRCP_DOWNLINK_PORT_OFFSET), 130 GET_U_1(cp + RRCP_UPLINK_PORT_OFFSET), 131 GET_ETHERADDR_STRING(cp + RRCP_UPLINK_MAC_OFFSET), 132 GET_BE_U_4(cp + RRCP_VENDOR_ID_OFFSET), 133 GET_BE_U_2(cp + RRCP_CHIP_ID_OFFSET)); 134 }else if (rrcp_opcode==RRCP_OPCODE_GET_CONFIGURATION || 135 rrcp_opcode==RRCP_OPCODE_SET_CONFIGURATION){ 136 ND_PRINT(", cookie=0x%08x%08x ", 137 GET_BE_U_4(cp + RRCP_COOKIE2_OFFSET), 138 GET_BE_U_4(cp + RRCP_COOKIE1_OFFSET)); 139 } 140 } 141 142 /* 143 * Print Realtek packets. 144 * 145 * See, for example, section 8.22 "Realtek Echo Protocol" of 146 * 147 * http://realtek.info/pdf/rtl8324.pdf 148 * 149 * and section 7.24 "Realtek Echo Protocol" of 150 * 151 * http://realtek.info/pdf/rtl8326.pdf 152 * 153 * for information on REP. 154 * 155 * See section 8.21 "Network Loop Connection Fault Detection" of 156 * 157 * http://realtek.info/pdf/rtl8324.pdf 158 * 159 * and section 7.23 "Network Loop Connection Fault Detection" of 160 * 161 * http://realtek.info/pdf/rtl8326.pdf 162 * 163 * for information on RLDP. 164 * 165 * See also section 7.3.8 "Loop Detection" of 166 * 167 * http://www.ibselectronics.com/ibsstore/datasheet/RTL8306E-CG.pdf 168 * 169 * (revision 1.1 of the RTL8306E-CG datasheet), which describes a loop 170 * detection protocol for which the payload has a 16-bit (presumably 171 * big-endian) field containing the value 0x0300, followed by what is 172 * presumably a 16-bit big-endian field the upper 12 bits of which are 0 173 * and the lower 4 bits of which are a TTL value, followed by zeroes to 174 * pad the packet out to the minimum Ethernet packet size. 175 * 176 * See also section 7.3.13 "Loop Detection" of 177 * 178 * http://realtek.info/pdf/rtl8305sb.pdf 179 * 180 * (revision 1.3 of the RTL8305SB datasheet), which describes a similar 181 * loop detection protocol that lacks the TTL field - all the bytes 182 * after 0x0300 are zero. 183 * 184 * See also section 7.3.7 "Loop Detection" of 185 * 186 * https://datasheet.lcsc.com/lcsc/1810221720_Realtek-Semicon-RTL8305NB-CG_C52146.pdf 187 * 188 * (revision 1.0 of the RTL8305NB-CT datasheet), which describes a loop 189 * detection protocol similar to the one from the RTL8306E-CG datasheet, 190 * except that the first value is 0x2300, not 0x0300. 191 * 192 * And, on top of all that, I've seen packets where the first octet of 193 * the packet is 0x23, and that's followed by 6 unknown octets (a MAC 194 * address of some sort? It differs from packet to packet in a capture), 195 * followed by the MAC address that appears in the source address in the 196 * Ethernet header (possibly the originator, in case the packet is forwarded, 197 * in which case the forwarded packets won't have the source address from 198 * the Ethernet header there), followed by unknown stuff (0x0d followed by 199 * zeroes for all such packets in one capture, 0x01 followed by zeroes for 200 * all such packets in another capture, 0x07 followed by 0x20's for all 201 * such packets in yet another capture). The OpenRRCP issue at 202 * https://github.com/illarionov/OpenRRCP/issues/3 shows a capture 203 * similar to the last of those, but with 0x02 instead of 0x07. Or is that 204 * just crap in the buffer in which the chip constructed the packet, left 205 * over from something else? 206 */ 207 void 208 rtl_print(netdissect_options *ndo, 209 const u_char *cp, 210 u_int length _U_, 211 const struct lladdr_info *src, 212 const struct lladdr_info *dst) 213 { 214 uint8_t rtl_proto; 215 216 ndo->ndo_protocol = "rtl"; 217 218 if (src != NULL && dst != NULL) { 219 ND_PRINT("%s > %s, ", 220 (src->addr_string)(ndo, src->addr), 221 (dst->addr_string)(ndo, dst->addr)); 222 } 223 224 rtl_proto = GET_U_1(cp + RTL_PROTOCOL_OFFSET); 225 226 if (rtl_proto == RTL_PROTOCOL_RRCP) 227 rrcp_print(ndo, cp); 228 else if (rtl_proto == RTL_PROTOCOL_REP) { 229 /* 230 * REP packets have no payload. 231 */ 232 ND_PRINT("REP"); 233 } else if (rtl_proto == RTL_PROTOCOL_RLDP || 234 rtl_proto == RTL_PROTOCOL_RLDP2) { 235 /* 236 * RLDP packets have no payload. 237 * (XXX - except when they do? See above.) 238 */ 239 ND_PRINT("RLDP"); 240 } else if (rtl_proto == RTL_PROTOCOL_XXX_DSA) 241 ND_PRINT("Realtek 8-byte DSA tag"); 242 else if ((rtl_proto & 0xF0) == RTL_PROTOCOL_8306_DSA) 243 ND_PRINT("Realtek RTL8306 4-byte DSA tag"); 244 else if ((rtl_proto & 0xF0) == RTL_PROTOCOL_8366RB_DSA) 245 ND_PRINT("Realtek RTL8366RB 4-byte DSA tag"); 246 else 247 ND_PRINT("Realtek unknown type 0x%02x", rtl_proto); 248 } 249