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