]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Support more Realtek protocols than RRCP.
authorGuy Harris <[email protected]>
Sun, 23 Jan 2022 09:44:16 +0000 (01:44 -0800)
committerGuy Harris <[email protected]>
Sun, 23 Jan 2022 09:44:16 +0000 (01:44 -0800)
The Ethertype 0x8899 is used by Realtek for several over-the-wire
protocols, as well as for supplying tag information to a host CPU from a
Realtek chip.  Add code to handle protocols other than RRCP, although we
don't fully dissect all of them.

ethertype.h
netdissect.h
print-ether.c
print-rrcp.c

index a757a39c2fc64c44a07a94e38f1aba1b31b74e68..8f8acff0459753da2d4f17e2e31fee44f82fc1c1 100644 (file)
 #ifndef ETHERTYPE_EAPOL
 #define ETHERTYPE_EAPOL        0x888e
 #endif
 #ifndef ETHERTYPE_EAPOL
 #define ETHERTYPE_EAPOL        0x888e
 #endif
-#ifndef ETHERTYPE_RRCP
-#define ETHERTYPE_RRCP         0x8899
+#ifndef ETHERTYPE_REALTEK
+#define ETHERTYPE_REALTEK      0x8899  /* Realtek layer 2 protocols and switch tags */
 #endif
 #ifndef ETHERTYPE_AOE
 #define ETHERTYPE_AOE                  0x88a2
 #endif
 #ifndef ETHERTYPE_AOE
 #define ETHERTYPE_AOE                  0x88a2
index a10ffa3b6b566e765ed628f465cde1680dbf1a86..867be794032c78e84fe1f85258faf6ff35557f20 100644 (file)
@@ -710,9 +710,9 @@ extern void resp_print(netdissect_options *, const u_char *, u_int);
 extern void rip_print(netdissect_options *, const u_char *, u_int);
 extern void ripng_print(netdissect_options *, const u_char *, unsigned int);
 extern void rpki_rtr_print(netdissect_options *, const u_char *, u_int);
 extern void rip_print(netdissect_options *, const u_char *, u_int);
 extern void ripng_print(netdissect_options *, const u_char *, unsigned int);
 extern void rpki_rtr_print(netdissect_options *, const u_char *, u_int);
-extern void rrcp_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *, const struct lladdr_info *);
 extern void rsvp_print(netdissect_options *, const u_char *, u_int);
 extern int rt6_print(netdissect_options *, const u_char *, const u_char *);
 extern void rsvp_print(netdissect_options *, const u_char *, u_int);
 extern int rt6_print(netdissect_options *, const u_char *, const u_char *);
+extern void rtl_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *, const struct lladdr_info *);
 extern void rtsp_print(netdissect_options *, const u_char *, u_int);
 extern void rx_print(netdissect_options *, const u_char *, u_int, uint16_t, uint16_t, const u_char *);
 extern void sctp_print(netdissect_options *, const u_char *, const u_char *, u_int);
 extern void rtsp_print(netdissect_options *, const u_char *, u_int);
 extern void rx_print(netdissect_options *, const u_char *, u_int, uint16_t, uint16_t, const u_char *);
 extern void sctp_print(netdissect_options *, const u_char *, const u_char *, u_int);
index d20addbf91c5aad5bdf601aa90e5b9d2a428df2f..5607bfc3ba5a00951c057bdaa73e4097e4e7e7de 100644 (file)
@@ -86,7 +86,7 @@ const struct tok ethertype_values[] = {
     { ETHERTYPE_PPPOED,         "PPPoE D" },
     { ETHERTYPE_PPPOES,         "PPPoE S" },
     { ETHERTYPE_EAPOL,          "EAPOL" },
     { ETHERTYPE_PPPOED,         "PPPoE D" },
     { ETHERTYPE_PPPOES,         "PPPoE S" },
     { ETHERTYPE_EAPOL,          "EAPOL" },
-    { ETHERTYPE_RRCP,           "RRCP" },
+    { ETHERTYPE_REALTEK,        "Realtek protocols" },
     { ETHERTYPE_MS_NLB_HB,      "MS NLB heartbeat" },
     { ETHERTYPE_JUMBO,          "Jumbo" },
     { ETHERTYPE_NSH,            "NSH" },
     { ETHERTYPE_MS_NLB_HB,      "MS NLB heartbeat" },
     { ETHERTYPE_JUMBO,          "Jumbo" },
     { ETHERTYPE_NSH,            "NSH" },
@@ -584,8 +584,8 @@ ethertype_print(netdissect_options *ndo,
                eapol_print(ndo, p);
                return (1);
 
                eapol_print(ndo, p);
                return (1);
 
-       case ETHERTYPE_RRCP:
-               rrcp_print(ndo, p, length, src, dst);
+       case ETHERTYPE_REALTEK:
+               rtl_print(ndo, p, length, src, dst);
                return (1);
 
        case ETHERTYPE_PPP:
                return (1);
 
        case ETHERTYPE_PPP:
index 9803f75fe4fabc7af0ab0661a7c55b9a394a9b40..416d041e69f642b187f1315e26cb292724f6836c 100644 (file)
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * Format and print Realtek Remote Control Protocol (RRCP)
- * and Realtek Echo Protocol (RRCP-REP) packets.
+ * Format and print Realtek Remote Control Protocol (RRCP), Realtek
+ * Loop Detection Protocol (RLDP), and Realtek Echo Protocol (REP) packets,
+ * as well as tag formats used by some Realtek switch chips to supply
+ * tag information to a host CPU for a switch.
  */
 
  */
 
-/* \summary: Realtek Remote Control Protocol (RRCP) printer */
+/* \summary: printer for various Realtek protocols */
 
 /*
  * See, for example, section 8.20 "Realtek Remote Control Protocol" of
 
 /*
  * See, for example, section 8.20 "Realtek Remote Control Protocol" of
  *
  *    http://openrrcp.org.ru/wiki/rrcp_protocol
  *
  *
  *    http://openrrcp.org.ru/wiki/rrcp_protocol
  *
+ * for information on RRCP.
+ *
+ * See, for example, section 8.21 "Network Loop Connection Fault
+ * Detection" of
+ *
+ *    http://realtek.info/pdf/rtl8324.pdf
+ *
+ * and section 7.23 "Network Loop Connection Fault Detection" of
+ *
+ *    http://realtek.info/pdf/rtl8326.pdf
+ *
+ * for information on RLDP.
+ *
+ * See, for example, section 8.22 "Realtek Echo Protocol" of
+ *
+ *    http://realtek.info/pdf/rtl8324.pdf
+ *
+ * and section 7.24 "Realtek Echo Protocol" of
+ *
+ *    http://realtek.info/pdf/rtl8326.pdf
+ *
+ * for information on REP.
+ *
  * NOTE: none of them indicate the byte order of multi-byte fields in any
  * obvious fashion.
  * NOTE: none of them indicate the byte order of multi-byte fields in any
  * obvious fashion.
+ *
+ * See section 8.10 "CPU Tag Function" of
+ *
+ *    http://realtek.info/pdf/rtl8306sd%28m%29_datasheet_1.1.pdf
+ *
+ * for the RTL8306 DSA protocol tag format.
  */
 
 #ifdef HAVE_CONFIG_H
  */
 
 #ifdef HAVE_CONFIG_H
 #include "addrtoname.h"
 #include "extract.h"
 
 #include "addrtoname.h"
 #include "extract.h"
 
-#define RRCP_OPCODE_MASK       0x7F    /* 0x00 = hello, 0x01 = get, 0x02 = set */
-#define RRCP_ISREPLY           0x80    /* 0 = request to switch, 0x80 = reply from switch */
+#define RTL_FRAME_TYPE_OFFSET          0       /* frame type and other data - 1 byte */
+
+/*
+ * The upper 4 bits of the first octet of Realtek 0x8899 frames indicates
+ * the frame type.
+ */
+#define RTL_FRAME_TYPE_MASK            0xF0
+#define RTL_FRAME_TYPE_SUBTYPE         0x00    /* lower 4 bits are a subtype */
+#define RTL_FRAME_TYPE_8306_DSA                0x90    /* RTL8306 DSA protocol */
+#define RTL_FRAME_TYPE_8366RB_DSA      0xA0    /* RTL8366RB DSA protocol */
+#define RTL_FRAME_TYPE_SHIFT           4
+
+/*
+ * The lower 4 bits are a subtype if the upper 4 bits are 0.
+ */
+#define RTL_FRAME_SUBTYPE_MASK         0x0F
+#define RTL_FRAME_SUBTYPE_RRCP         0x01    /* RRCP */
+#define RTL_FRAME_SUBTYPE_REP          0x02    /* REP */
+#define RTL_FRAME_SUBTYPE_RLDP         0x03    /* RLDP */
+#define RTL_FRAME_SUBTYPE_XXX_DSA      0x04    /* DSA protocol for some chip(s) */
 
 
-#define RRCP_PROTO_OFFSET              0       /* proto - 1 byte, must be 1 */
 #define RRCP_OPCODE_ISREPLY_OFFSET     1       /* opcode and isreply flag - 1 byte */
 #define RRCP_OPCODE_ISREPLY_OFFSET     1       /* opcode and isreply flag - 1 byte */
+
+#define RRCP_OPCODE_MASK               0x7F    /* 0x00 = hello, 0x01 = get, 0x02 = set */
+#define RRCP_ISREPLY                   0x80    /* 0 = request to switch, 0x80 = reply from switch */
+
+#define RRCP_OPCODE_HELLO              0x00
+#define RRCP_OPCODE_GET_CONFIGURATION  0x01
+#define RRCP_OPCODE_SET_CONFIGURATION  0x02
+
 #define RRCP_AUTHKEY_OFFSET            2       /* authorization key - 2 bytes, 0x2379 by default */
 
 /* most packets */
 #define RRCP_AUTHKEY_OFFSET            2       /* authorization key - 2 bytes, 0x2379 by default */
 
 /* most packets */
 #define RRCP_CHIP_ID_OFFSET            12      /* 2 bytes */
 #define RRCP_VENDOR_ID_OFFSET          14      /* 4 bytes */
 
 #define RRCP_CHIP_ID_OFFSET            12      /* 2 bytes */
 #define RRCP_VENDOR_ID_OFFSET          14      /* 4 bytes */
 
-static const struct tok proto_values[] = {
-       { 1, "RRCP" },
-       { 2, "RRCP-REP" },
-       { 0, NULL }
-};
-
 static const struct tok opcode_values[] = {
 static const struct tok opcode_values[] = {
-       { 0, "hello" },
-       { 1, "get" },
-       { 2, "set" },
+       { RRCP_OPCODE_HELLO,             "hello" },
+       { RRCP_OPCODE_GET_CONFIGURATION, "get" },
+       { RRCP_OPCODE_SET_CONFIGURATION, "set" },
        { 0, NULL }
 };
 
 /*
        { 0, NULL }
 };
 
 /*
- * Print RRCP requests
+ * Print RRCP packets
  */
  */
-void
+static void
 rrcp_print(netdissect_options *ndo,
 rrcp_print(netdissect_options *ndo,
-         const u_char *cp,
-         u_int length _U_,
-         const struct lladdr_info *src,
-         const struct lladdr_info *dst)
+         const u_char *cp)
 {
 {
-       uint8_t rrcp_proto;
        uint8_t rrcp_opcode;
 
        ndo->ndo_protocol = "rrcp";
        uint8_t rrcp_opcode;
 
        ndo->ndo_protocol = "rrcp";
-       rrcp_proto = GET_U_1(cp + RRCP_PROTO_OFFSET);
        rrcp_opcode = GET_U_1((cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_OPCODE_MASK;
        rrcp_opcode = GET_U_1((cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_OPCODE_MASK;
-       if (src != NULL && dst != NULL) {
-               ND_PRINT("%s > %s, ",
-                       (src->addr_string)(ndo, src->addr),
-                       (dst->addr_string)(ndo, dst->addr));
-       }
-       ND_PRINT("%s %s",
-               tok2str(proto_values,"RRCP-0x%02x",rrcp_proto),
-               ((GET_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY) ? "reply" : "query");
-       if (rrcp_proto==1){
-           ND_PRINT(": %s",
-                    tok2str(opcode_values,"unknown opcode (0x%02x)",rrcp_opcode));
-       }
-       if (rrcp_opcode==1 || rrcp_opcode==2){
+       ND_PRINT("RRCP %s: %s",
+               ((GET_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY) ? "reply" : "query",
+               tok2str(opcode_values,"unknown opcode (0x%02x)",rrcp_opcode));
+       if (rrcp_opcode==RRCP_OPCODE_GET_CONFIGURATION ||
+           rrcp_opcode==RRCP_OPCODE_SET_CONFIGURATION){
            ND_PRINT(" addr=0x%04x, data=0x%08x",
                     GET_LE_U_2(cp + RRCP_REG_ADDR_OFFSET),
                     GET_LE_U_4(cp + RRCP_REG_DATA_OFFSET));
        }
            ND_PRINT(" addr=0x%04x, data=0x%08x",
                     GET_LE_U_2(cp + RRCP_REG_ADDR_OFFSET),
                     GET_LE_U_4(cp + RRCP_REG_DATA_OFFSET));
        }
-       if (rrcp_proto==1){
-           ND_PRINT(", auth=0x%04x",
-                 GET_BE_U_2(cp + RRCP_AUTHKEY_OFFSET));
-       }
-       if (rrcp_proto==1 && rrcp_opcode==0 &&
+       ND_PRINT(", auth=0x%04x",
+                GET_BE_U_2(cp + RRCP_AUTHKEY_OFFSET));
+       if (rrcp_opcode==RRCP_OPCODE_HELLO &&
             ((GET_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY)){
            ND_PRINT(" downlink_port=%u, uplink_port=%u, uplink_mac=%s, vendor_id=%08x ,chip_id=%04x ",
                     GET_U_1(cp + RRCP_DOWNLINK_PORT_OFFSET),
             ((GET_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY)){
            ND_PRINT(" downlink_port=%u, uplink_port=%u, uplink_mac=%s, vendor_id=%08x ,chip_id=%04x ",
                     GET_U_1(cp + RRCP_DOWNLINK_PORT_OFFSET),
@@ -128,9 +163,84 @@ rrcp_print(netdissect_options *ndo,
                     GET_ETHERADDR_STRING(cp + RRCP_UPLINK_MAC_OFFSET),
                     GET_BE_U_4(cp + RRCP_VENDOR_ID_OFFSET),
                     GET_BE_U_2(cp + RRCP_CHIP_ID_OFFSET));
                     GET_ETHERADDR_STRING(cp + RRCP_UPLINK_MAC_OFFSET),
                     GET_BE_U_4(cp + RRCP_VENDOR_ID_OFFSET),
                     GET_BE_U_2(cp + RRCP_CHIP_ID_OFFSET));
-       }else if (rrcp_opcode==1 || rrcp_opcode==2 || rrcp_proto==2){
+       }else if (rrcp_opcode==RRCP_OPCODE_GET_CONFIGURATION ||
+                 rrcp_opcode==RRCP_OPCODE_SET_CONFIGURATION){
            ND_PRINT(", cookie=0x%08x%08x ",
                    GET_BE_U_4(cp + RRCP_COOKIE2_OFFSET),
                    GET_BE_U_4(cp + RRCP_COOKIE1_OFFSET));
        }
 }
            ND_PRINT(", cookie=0x%08x%08x ",
                    GET_BE_U_4(cp + RRCP_COOKIE2_OFFSET),
                    GET_BE_U_4(cp + RRCP_COOKIE1_OFFSET));
        }
 }
+
+/*
+ * Print Realtek packets
+ */
+void
+rtl_print(netdissect_options *ndo,
+         const u_char *cp,
+         u_int length _U_,
+         const struct lladdr_info *src,
+         const struct lladdr_info *dst)
+{
+       uint8_t rtl_proto;
+
+       ndo->ndo_protocol = "rtl";
+
+       if (src != NULL && dst != NULL) {
+               ND_PRINT("%s > %s, ",
+                       (src->addr_string)(ndo, src->addr),
+                       (dst->addr_string)(ndo, dst->addr));
+       }
+
+       rtl_proto = GET_U_1(cp + RTL_FRAME_TYPE_OFFSET);
+
+       switch (rtl_proto & RTL_FRAME_TYPE_MASK) {
+
+       case RTL_FRAME_TYPE_SUBTYPE:
+               /*
+                * Test the subtype.
+                */
+               switch (rtl_proto & RTL_FRAME_SUBTYPE_MASK) {
+
+               case RTL_FRAME_SUBTYPE_RRCP:
+                       rrcp_print(ndo, cp);
+                       break;
+
+               case RTL_FRAME_SUBTYPE_REP:
+                       /*
+                        * REP packets have no payload.
+                        */
+                       ND_PRINT("REP");
+                       break;
+
+               case RTL_FRAME_SUBTYPE_RLDP:
+                       /*
+                        * RLDP packets have no payload.
+                        */
+                       ND_PRINT("RLDP");
+                       break;
+
+               case RTL_FRAME_SUBTYPE_XXX_DSA:
+                       ND_PRINT("Realtek 8-byte DSA tag");
+                       break;
+
+               default:
+                       ND_PRINT("Realtek unknown subtype 0x%01x",
+                           rtl_proto & RTL_FRAME_SUBTYPE_MASK);
+                       break;
+               }
+               break;
+
+       case RTL_FRAME_TYPE_8306_DSA:
+               ND_PRINT("Realtek RTL8306 4-byte DSA tag");
+               break;
+
+       case RTL_FRAME_TYPE_8366RB_DSA:
+               ND_PRINT("Realtek RTL8366RB 4-byte DSA tag");
+               break;
+
+       default:
+               ND_PRINT("Realtek unknown type 0x%01x",
+                   (rtl_proto & RTL_FRAME_TYPE_MASK) >> RTL_FRAME_TYPE_SHIFT);
+               break;
+       }
+}