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) 21 * and Realtek Echo Protocol (RRCP-REP) packets. 22 */ 23 24 /* \summary: Realtek Remote Control Protocol (RRCP) printer */ 25 26 #ifdef HAVE_CONFIG_H 27 #include "config.h" 28 #endif 29 30 #include <netdissect-stdinc.h> 31 32 #include "netdissect.h" 33 #include "addrtoname.h" 34 #include "extract.h" 35 #include "ether.h" 36 37 #define RRCP_OPCODE_MASK 0x7F /* 0x00 = hello, 0x01 = get, 0x02 = set */ 38 #define RRCP_ISREPLY 0x80 /* 0 = request to switch, 0x80 = reply from switch */ 39 40 #define RRCP_PROTO_OFFSET 0 /* proto - 1 byte, must be 1 */ 41 #define RRCP_OPCODE_ISREPLY_OFFSET 1 /* opcode and isreply flag - 1 byte */ 42 #define RRCP_AUTHKEY_OFFSET 2 /* authorization key - 2 bytes, 0x2379 by default */ 43 44 /* most packets */ 45 #define RRCP_REG_ADDR_OFFSET 4 /* register address - 2 bytes */ 46 #define RRCP_REG_DATA_OFFSET 6 /* register data - 4 bytes */ 47 #define RRCP_COOKIE1_OFFSET 10 /* 4 bytes */ 48 #define RRCP_COOKIE2_OFFSET 14 /* 4 bytes */ 49 50 /* hello reply packets */ 51 #define RRCP_DOWNLINK_PORT_OFFSET 4 /* 1 byte */ 52 #define RRCP_UPLINK_PORT_OFFSET 5 /* 1 byte */ 53 #define RRCP_UPLINK_MAC_OFFSET 6 /* 6 byte MAC address */ 54 #define RRCP_CHIP_ID_OFFSET 12 /* 2 bytes */ 55 #define RRCP_VENDOR_ID_OFFSET 14 /* 4 bytes */ 56 57 static const struct tok proto_values[] = { 58 { 1, "RRCP" }, 59 { 2, "RRCP-REP" }, 60 { 0, NULL } 61 }; 62 63 static const struct tok opcode_values[] = { 64 { 0, "hello" }, 65 { 1, "get" }, 66 { 2, "set" }, 67 { 0, NULL } 68 }; 69 70 /* 71 * Print RRCP requests 72 */ 73 void 74 rrcp_print(netdissect_options *ndo, 75 register const u_char *cp, 76 u_int length _U_, 77 const struct lladdr_info *src, 78 const struct lladdr_info *dst) 79 { 80 uint8_t rrcp_proto; 81 uint8_t rrcp_opcode; 82 83 ND_TCHECK(*(cp + RRCP_PROTO_OFFSET)); 84 rrcp_proto = *(cp + RRCP_PROTO_OFFSET); 85 ND_TCHECK(*(cp + RRCP_OPCODE_ISREPLY_OFFSET)); 86 rrcp_opcode = (*(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_OPCODE_MASK; 87 if (src != NULL && dst != NULL) { 88 ND_PRINT((ndo, "%s > %s, ", 89 (src->addr_string)(ndo, src->addr), 90 (dst->addr_string)(ndo, dst->addr))); 91 } 92 ND_PRINT((ndo, "%s %s", 93 tok2str(proto_values,"RRCP-0x%02x",rrcp_proto), 94 ((*(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY) ? "reply" : "query")); 95 if (rrcp_proto==1){ 96 ND_PRINT((ndo, ": %s", 97 tok2str(opcode_values,"unknown opcode (0x%02x)",rrcp_opcode))); 98 } 99 if (rrcp_opcode==1 || rrcp_opcode==2){ 100 ND_TCHECK2(*(cp + RRCP_REG_ADDR_OFFSET), 6); 101 ND_PRINT((ndo, " addr=0x%04x, data=0x%08x", 102 EXTRACT_LE_16BITS(cp + RRCP_REG_ADDR_OFFSET), 103 EXTRACT_LE_32BITS(cp + RRCP_REG_DATA_OFFSET))); 104 } 105 if (rrcp_proto==1){ 106 ND_TCHECK2(*(cp + RRCP_AUTHKEY_OFFSET), 2); 107 ND_PRINT((ndo, ", auth=0x%04x", 108 EXTRACT_16BITS(cp + RRCP_AUTHKEY_OFFSET))); 109 } 110 if (rrcp_proto==1 && rrcp_opcode==0 && 111 ((*(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY)){ 112 ND_TCHECK2(*(cp + RRCP_VENDOR_ID_OFFSET), 4); 113 ND_PRINT((ndo, " downlink_port=%d, uplink_port=%d, uplink_mac=%s, vendor_id=%08x ,chip_id=%04x ", 114 *(cp + RRCP_DOWNLINK_PORT_OFFSET), 115 *(cp + RRCP_UPLINK_PORT_OFFSET), 116 etheraddr_string(ndo, cp + RRCP_UPLINK_MAC_OFFSET), 117 EXTRACT_32BITS(cp + RRCP_VENDOR_ID_OFFSET), 118 EXTRACT_16BITS(cp + RRCP_CHIP_ID_OFFSET))); 119 }else if (rrcp_opcode==1 || rrcp_opcode==2 || rrcp_proto==2){ 120 ND_TCHECK2(*(cp + RRCP_COOKIE2_OFFSET), 4); 121 ND_PRINT((ndo, ", cookie=0x%08x%08x ", 122 EXTRACT_32BITS(cp + RRCP_COOKIE2_OFFSET), 123 EXTRACT_32BITS(cp + RRCP_COOKIE1_OFFSET))); 124 } 125 return; 126 127 trunc: 128 ND_PRINT((ndo, "[|rrcp]")); 129 } 130