1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <sys/types.h> 28 #include <sys/stropts.h> 29 #include <sys/stream.h> 30 #include <sys/dlpi.h> 31 #include <sys/hook.h> 32 #include <sys/hook_event.h> 33 #include <inet/led.h> 34 #include <inet/common.h> 35 #include <inet/mi.h> 36 #include <inet/arp.h> 37 #include <inet/ip.h> 38 #include <netinet/arp.h> 39 40 #include <mdb/mdb_modapi.h> 41 #include <mdb/mdb_ks.h> 42 43 typedef struct { 44 uint32_t act_cmd; 45 char *act_name; 46 char *act_type; 47 } arp_cmd_tbl; 48 49 /* 50 * removed all the ace/arl related stuff. The only thing that remains 51 * is code for dealing with ioctls and printing out arp header that 52 * should probably be moved into the ip/mdb module. 53 */ 54 55 /* 56 * Print an ARP hardware and protocol address pair; used when printing an ARP 57 * message. 58 */ 59 static void 60 print_arp(char field_id, const uchar_t *buf, const arh_t *arh, uint16_t ptype) 61 { 62 char macstr[ARP_MAX_ADDR_LEN*3]; 63 in_addr_t inaddr; 64 65 if (arh->arh_hlen == 0) 66 (void) strcpy(macstr, "(none)"); 67 else 68 mdb_mac_addr(buf, arh->arh_hlen, macstr, sizeof (macstr)); 69 mdb_printf("%?s ar$%cha %s\n", "", field_id, macstr); 70 if (arh->arh_plen == 0) { 71 mdb_printf("%?s ar$%cpa (none)\n", "", field_id); 72 } else if (ptype == IP_ARP_PROTO_TYPE) { 73 mdb_printf("%?s ar$%cpa (unknown)\n", "", field_id); 74 } else if (arh->arh_plen == sizeof (in_addr_t)) { 75 (void) memcpy(&inaddr, buf + arh->arh_hlen, sizeof (inaddr)); 76 mdb_printf("%?s ar$%cpa %I\n", "", field_id, inaddr); 77 } else { 78 mdb_printf("%?s ar$%cpa (malformed IP)\n", "", field_id); 79 } 80 } 81 82 /* 83 * Decode an ARP message and display it. 84 */ 85 /* ARGSUSED2 */ 86 static int 87 arphdr_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 88 { 89 struct { 90 arh_t arh; 91 uchar_t addrs[4 * ARP_MAX_ADDR_LEN]; 92 } arp; 93 size_t blen; 94 uint16_t htype, ptype, op; 95 const char *cp; 96 97 if (!(flags & DCMD_ADDRSPEC)) { 98 mdb_warn("address required to print ARP header\n"); 99 return (DCMD_ERR); 100 } 101 102 if (mdb_vread(&arp.arh, sizeof (arp.arh), addr) == -1) { 103 mdb_warn("unable to read ARP header at %p", addr); 104 return (DCMD_ERR); 105 } 106 mdb_nhconvert(&htype, arp.arh.arh_hardware, sizeof (htype)); 107 mdb_nhconvert(&ptype, arp.arh.arh_proto, sizeof (ptype)); 108 mdb_nhconvert(&op, arp.arh.arh_operation, sizeof (op)); 109 110 switch (htype) { 111 case ARPHRD_ETHER: 112 cp = "Ether"; 113 break; 114 case ARPHRD_IEEE802: 115 cp = "IEEE802"; 116 break; 117 case ARPHRD_IB: 118 cp = "InfiniBand"; 119 break; 120 default: 121 cp = "Unknown"; 122 break; 123 } 124 mdb_printf("%?p: ar$hrd %x (%s)\n", addr, htype, cp); 125 mdb_printf("%?s ar$pro %x (%s)\n", "", ptype, 126 ptype == IP_ARP_PROTO_TYPE ? "IP" : "Unknown"); 127 128 switch (op) { 129 case ARPOP_REQUEST: 130 cp = "ares_op$REQUEST"; 131 break; 132 case ARPOP_REPLY: 133 cp = "ares_op$REPLY"; 134 break; 135 case REVARP_REQUEST: 136 cp = "arev_op$REQUEST"; 137 break; 138 case REVARP_REPLY: 139 cp = "arev_op$REPLY"; 140 break; 141 default: 142 cp = "Unknown"; 143 break; 144 } 145 mdb_printf("%?s ar$op %d (%s)\n", "", op, cp); 146 147 /* 148 * Note that we go to some length to attempt to print out the fixed 149 * header data before trying to decode the variable-length data. This 150 * is done to maximize the amount of useful information shown when the 151 * buffer is truncated or otherwise corrupt. 152 */ 153 blen = 2 * (arp.arh.arh_hlen + arp.arh.arh_plen); 154 if (mdb_vread(&arp.addrs, blen, addr + sizeof (arp.arh)) == -1) { 155 mdb_warn("unable to read ARP body at %p", addr); 156 return (DCMD_ERR); 157 } 158 159 print_arp('s', arp.addrs, &arp.arh, ptype); 160 print_arp('t', arp.addrs + arp.arh.arh_hlen + arp.arh.arh_plen, 161 &arp.arh, ptype); 162 return (DCMD_OK); 163 } 164 165 static const mdb_dcmd_t dcmds[] = { 166 { "arphdr", ":", "display an ARP header", arphdr_cmd, NULL }, 167 { NULL } 168 }; 169 170 /* Note: ar_t walker is in genunix.c and net.c; generic MI walker */ 171 static const mdb_walker_t walkers[] = { 172 { NULL } 173 }; 174 175 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 176 177 const mdb_modinfo_t * 178 _mdb_init(void) 179 { 180 return (&modinfo); 181 } 182 183 void 184 _mdb_fini(void) 185 { 186 } 187