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